udp works to netcat listener
This commit is contained in:
parent
6507956a83
commit
324aa59de4
|
@ -0,0 +1,91 @@
|
|||
import asyncio
|
||||
|
||||
from lib.logging import logger, LogLevel
|
||||
from lib.networking.cell_modem import cell_modem, DEBUG_XBEE
|
||||
from lib.runtime import runtime_timeout
|
||||
|
||||
|
||||
async def cell_udp_open(host: str, port: int):
|
||||
# Perform a DNS resolution to get the IP of the host
|
||||
cdnsgip = (await cell_modem.send_and_receive(f'AT+CDNSGIP="{host}"'.encode(), timeout=10000))
|
||||
if not len(cdnsgip):
|
||||
logger(f'Failed to get IP of "{host}" -> {cdnsgip}', source='CELL', level=LogLevel.error)
|
||||
return False
|
||||
ip = None
|
||||
if host in cdnsgip[0]:
|
||||
# Find the start of the IP address
|
||||
start = cdnsgip[0].find(',"', cdnsgip[0].find(host))
|
||||
if start != -1:
|
||||
start += 2 # Skip the ," characters
|
||||
# Find the end of the IP address
|
||||
end = cdnsgip[0].find('"', start)
|
||||
if end != -1:
|
||||
# Extract the IP address
|
||||
ip = cdnsgip[start:end]
|
||||
if not ip:
|
||||
ip = host
|
||||
|
||||
cipopen = await cell_modem.send_and_receive(f'AT+CIPOPEN=0,"UDP","{ip}",{port},8000'.encode())
|
||||
if cipopen[0] != '+CIPOPEN: 0,0':
|
||||
logger(f'Failed to open UDP connection to "{host}:{port}" -> {cipopen}', source='CELL', level=LogLevel.error)
|
||||
return False
|
||||
return ip
|
||||
|
||||
|
||||
async def cell_udp_send(host: str, port: int, data: bytes):
|
||||
resolved_ip = await cell_udp_open(host, port)
|
||||
if resolved_ip is False:
|
||||
return False
|
||||
|
||||
buffer = b''
|
||||
found = False
|
||||
|
||||
data_len = len(data)
|
||||
cell_modem.uart.write(f'AT+CIPSEND=0,{data_len},"{resolved_ip}",{port}\r')
|
||||
await asyncio.sleep(0.1)
|
||||
cell_modem.uart.write(data)
|
||||
while not found:
|
||||
resp = await cell_modem.xb_read(1)
|
||||
if resp:
|
||||
if DEBUG_XBEE:
|
||||
logger(f'cell_udp_send :: {resp}', source='CELL', level=LogLevel.debug)
|
||||
buffer += resp
|
||||
if b'\r\nERROR' in buffer:
|
||||
return False
|
||||
else:
|
||||
for a in [b'OK\r\n\r\n+CIPSEND:', b'\r\nRECV FROM:']:
|
||||
if a in buffer:
|
||||
found = True
|
||||
return buffer
|
||||
|
||||
|
||||
async def cell_udp_close():
|
||||
await cell_modem.send_and_receive(b'AT+CIPCLOSE=0')
|
||||
|
||||
|
||||
async def cell_udp_receive(timeout: int):
|
||||
@runtime_timeout(timeout)
|
||||
async def inner():
|
||||
buffer = b''
|
||||
length = None
|
||||
while True:
|
||||
r = await cell_modem.xb_read(0.5)
|
||||
if r:
|
||||
buffer += r
|
||||
response = buffer.decode('utf-8')
|
||||
|
||||
# If we haven't found the length yet, try to find it
|
||||
if length is None:
|
||||
start = response.find('+IPD')
|
||||
if start > -1:
|
||||
end = response.find('\r\n', start)
|
||||
if end > -1: # We have found the length
|
||||
length = int(response[start + 4:end])
|
||||
response = response[end + 2:] # Remove '+IPD' and length from response
|
||||
buffer = response.encode() # Update buffer
|
||||
|
||||
# If we know the length, check if we have received the entire message
|
||||
if length is not None and len(buffer) >= length:
|
||||
return response[:length]
|
||||
|
||||
return await inner()
|
|
@ -19,6 +19,9 @@ bee_power_pin.value(0)
|
|||
|
||||
class ModemError(Exception):
|
||||
def __init__(self, message: str, sent_command: bytes, response: list):
|
||||
self.message = message
|
||||
self.sent_command = sent_command
|
||||
self.response = response
|
||||
super().__init__(f'{message}: {sent_command} -> {response}')
|
||||
|
||||
|
||||
|
@ -29,6 +32,8 @@ async def xb_toggle_power():
|
|||
|
||||
|
||||
class CellularModem:
|
||||
# TODO: add lock that is used in send_and_recieve as well as by things that do raw reading
|
||||
|
||||
def __init__(self):
|
||||
self.uart = UART(2, baudrate=115200, timeout=4, rx=PIN_BEE_UART_RXD, tx=PIN_BEE_UART_TXD)
|
||||
|
||||
|
@ -69,12 +74,14 @@ class CellularModem:
|
|||
data = b''
|
||||
expected_not_found = 0
|
||||
while time.ticks_diff(time.ticks_ms(), t) < timeout:
|
||||
read = await self.xb_read(50)
|
||||
read = await self.xb_read(0.5)
|
||||
if read and read != data_to_send:
|
||||
if VERBOSE_XBEE_COMM:
|
||||
print(f'<====@ {read}')
|
||||
data += read
|
||||
if read_until is not None and data.endswith(read_until):
|
||||
if b'ERROR' in data:
|
||||
raise ModemError('Recieved error', sent_command=data_to_send, response=data)
|
||||
elif read_until is not None and data.endswith(read_until):
|
||||
break
|
||||
elif expected is not None:
|
||||
if data.endswith(expected):
|
||||
|
@ -123,9 +130,11 @@ async def cellular_signal_strength():
|
|||
|
||||
async def cellular_ip() -> str:
|
||||
try:
|
||||
ip_resp = await cell_modem.send_and_receive(b'AT+IPADDR')
|
||||
if ip_resp[0].startswith('+IPADDR: '):
|
||||
return ip_resp[0].strip('+IPADDR: ')
|
||||
resp = await cell_modem.send_and_receive(b'AT+IPADDR')
|
||||
if len(resp) and resp[0].startswith('+IPADDR: '):
|
||||
return resp[0].strip('+IPADDR: ')
|
||||
else:
|
||||
return '0.0.0.0'
|
||||
except ModemError:
|
||||
return '0.0.0.0'
|
||||
|
||||
|
@ -133,6 +142,7 @@ async def cellular_ip() -> str:
|
|||
@runtime_timeout(CELLULAR_STARTUP_TIMEOUT)
|
||||
async def start_modem():
|
||||
await xb_toggle_power()
|
||||
cell_modem.xb_purge()
|
||||
while True:
|
||||
logger('Setting up modem', source='CELL')
|
||||
failures = 0
|
||||
|
@ -143,7 +153,10 @@ async def start_modem():
|
|||
break
|
||||
else:
|
||||
if DEBUG_XBEE:
|
||||
logger(f'Modem start failed: {at}', source='CELL', level=LogLevel.debug)
|
||||
msg = 'Modem start failed'
|
||||
if len(at):
|
||||
msg += str(at)
|
||||
logger(msg, source='CELL', level=LogLevel.debug)
|
||||
failures += 1
|
||||
if failures == 5:
|
||||
return False
|
||||
|
@ -166,10 +179,13 @@ async def start_modem():
|
|||
# Assuming model is SIM7600
|
||||
|
||||
cpin = await cell_modem.send_and_receive(b'AT+CPIN?')
|
||||
if not cpin[0].endswith(': READY'):
|
||||
if len(cpin) and not cpin[0].endswith(': READY'):
|
||||
logger('NO SIM CARD', source='CELL', level=LogLevel.error)
|
||||
await asyncio.sleep(30)
|
||||
return False
|
||||
elif not len(cpin):
|
||||
logger(f'SIM card check failed: {cpin}', source='CELL', level=LogLevel.error)
|
||||
return False
|
||||
|
||||
signal_strength = await cellular_signal_strength()
|
||||
logger(f'Signal strength: {signal_strength}', source='CELL')
|
||||
|
@ -211,16 +227,28 @@ async def start_modem():
|
|||
logger(f'Modem start failed: {b"AT+CGACT?"} -> {cgact}', source='CELL', level=LogLevel.error)
|
||||
return False
|
||||
|
||||
await cell_modem.send_and_receive(f'AT+CGSOCKCONT=1,"IP","{CELLULAR_APN}"'.encode())
|
||||
await cell_modem.send_and_receive(b'AT+CSOCKSETPN=1', read_until=None, expected=b'OK\r\n')
|
||||
await cell_modem.send_and_receive(b'AT+CIPMODE=0', read_until=None, expected=b'OK\r\n')
|
||||
await cell_modem.send_and_receive(b'AT+NETOPEN', read_until=None, expected=b'OK\r\n')
|
||||
try:
|
||||
await cell_modem.send_and_receive(f'AT+CGSOCKCONT=1,"IP","{CELLULAR_APN}"'.encode())
|
||||
await cell_modem.send_and_receive(b'AT+CSOCKSETPN=1', read_until=None, expected=b'OK\r\n')
|
||||
await cell_modem.send_and_receive(b'AT+CIPMODE=0', read_until=None, expected=b'OK\r\n')
|
||||
await cell_modem.send_and_receive(b'AT+NETOPEN', read_until=None, expected=b'OK\r\n')
|
||||
except ModemError as e:
|
||||
logger(f'Modem start failed: {e.message} :: {e.sent_command} -> {e.response}', source='CELL', level=LogLevel.error)
|
||||
return False
|
||||
|
||||
ip_get = await run_with_timeout(func=cellular_ip, timeout_sec=3)
|
||||
if not ip_get.failure:
|
||||
logger(f'IP: {ip_get.result}', source='CELL')
|
||||
else:
|
||||
logger(f'IP: 0.0.0.0', source='CELL')
|
||||
ip = None
|
||||
for i in range(10):
|
||||
ip_get = await run_with_timeout(func=cellular_ip, timeout_sec=3)
|
||||
if not ip_get.failure and ip_get.result != '0.0.0.0':
|
||||
ip = ip_get.result
|
||||
logger(f'IP: {ip}', source='CELL')
|
||||
break
|
||||
if DEBUG_XBEE:
|
||||
logger(f'Waiting for an IP', source='CELL', level=LogLevel.debug)
|
||||
await asyncio.sleep(1)
|
||||
if ip is None:
|
||||
logger(f'Did not get an IP', source='CELL', level=LogLevel.error)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
@ -229,11 +257,13 @@ async def start_modem_task():
|
|||
while True:
|
||||
if await start_modem():
|
||||
break
|
||||
if not (await cell_modem.send_and_receive(b'AT+CPOF')):
|
||||
try:
|
||||
if not (await cell_modem.send_and_receive(b'AT+CPOF')):
|
||||
await xb_toggle_power()
|
||||
except ModemError:
|
||||
await xb_toggle_power()
|
||||
await asyncio.sleep(2)
|
||||
|
||||
|
||||
logger('Modem ready', source='CELL')
|
||||
|
||||
while True:
|
||||
await asyncio.sleep(100)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
def freematics_checksum(data):
|
||||
cs = 0
|
||||
for i in data:
|
||||
cs += ord(i)
|
||||
return '{:02x}'.format(cs & 0xFF)
|
Loading…
Reference in New Issue