attempt at cell
This commit is contained in:
parent
6bc9f9c36c
commit
50ddf2c72e
|
@ -9,4 +9,5 @@ cp build/mpy-cross <project root>
|
|||
```
|
||||
|
||||
The `upload.sh` script will manage building this MicroPython project. If you get an error on the `Erase` step, that's
|
||||
fine and due to the files not existing to be erased.
|
||||
fine and due to the files not existing to be erased. Make sure you aren't connected to the device's serial port when
|
||||
running the script.
|
|
@ -5,7 +5,7 @@ import time
|
|||
import machine
|
||||
from machine import Pin
|
||||
|
||||
from config import CELLULAR_APN, CELLULAR_STARTUP_TIMEOUT
|
||||
from config import CELLULAR_APN, CELLULAR_STARTUP_TIMEOUT, TRACCAR_CONN_MODE
|
||||
from lib.logging import logger, LogLevel
|
||||
from lib.runtime import timeout, uTimeoutError, run_with_timeout
|
||||
|
||||
|
@ -15,7 +15,6 @@ PIN_BEE_UART_TXD = 2
|
|||
|
||||
bee_power_pin = Pin(PIN_BEE_POWER, Pin.OUT)
|
||||
bee_power_pin.value(0)
|
||||
time.sleep(0.5)
|
||||
bee_power_pin.value(1)
|
||||
|
||||
|
||||
|
@ -43,7 +42,7 @@ class CellularModem:
|
|||
if not res:
|
||||
raise OSError("Modem not responding")
|
||||
|
||||
async def send_command(self, command, require_ok: bool = False) -> tuple:
|
||||
async def send_command(self, command, require_ok: bool = False, expecing_plus: bool = False, read_until: bytes = None, clean_lines: bool = True) -> tuple:
|
||||
lines = []
|
||||
async with self._lock:
|
||||
while self.uart.any():
|
||||
|
@ -56,9 +55,20 @@ class CellularModem:
|
|||
lines.append(raw_line)
|
||||
if raw_line == b'ERROR\r\n':
|
||||
raise ModemErrorResponse(code=(command, lines))
|
||||
if len(lines) and lines[-1] == b'OK\r\n':
|
||||
break
|
||||
response = tuple(x for x in [x.decode().strip('\r\n') for x in lines] if len(x))
|
||||
if len(lines):
|
||||
print(raw_line)
|
||||
if expecing_plus:
|
||||
if lines[-1].decode().startswith('+'):
|
||||
break
|
||||
elif read_until:
|
||||
if lines[-1] == read_until:
|
||||
break
|
||||
elif lines[-1] == b'OK\r\n':
|
||||
break
|
||||
if clean_lines:
|
||||
response = tuple(x for x in [x.decode().strip('\r\n') for x in lines] if len(x))
|
||||
else:
|
||||
response = lines
|
||||
if require_ok:
|
||||
if response[-1] != 'OK':
|
||||
raise ModemErrorResponse(code=(command, lines))
|
||||
|
@ -70,7 +80,7 @@ cellular = CellularModem()
|
|||
|
||||
def _parse_csq(csq_value: int):
|
||||
if csq_value == 99:
|
||||
return 'disconnected'
|
||||
return 'unknown'
|
||||
elif csq_value == 31:
|
||||
return '51 dBm or greater'
|
||||
elif csq_value == 0:
|
||||
|
@ -84,7 +94,7 @@ def _parse_csq(csq_value: int):
|
|||
|
||||
|
||||
async def cellular_wake_modem():
|
||||
i = 5
|
||||
i = 2
|
||||
while i > 0:
|
||||
resp = await cellular.send_command('AT')
|
||||
if len(resp) == 1 and resp[0] == 'OK':
|
||||
|
@ -98,7 +108,11 @@ async def cellular_wake_modem():
|
|||
async def cellular_wait_cpsi():
|
||||
while True:
|
||||
cpsi_resp = await cellular.send_command('AT+CPSI?')
|
||||
parts = cpsi_resp[0].lstrip('+CPSI: ').split(',')
|
||||
try:
|
||||
parts = cpsi_resp[0].lstrip('+CPSI: ').split(',')
|
||||
except:
|
||||
print(cpsi_resp)
|
||||
raise
|
||||
if parts[1] == 'Online':
|
||||
return True, parts
|
||||
elif parts[1] == 'Low Power Mode':
|
||||
|
@ -140,20 +154,13 @@ async def cellular_signal_strength():
|
|||
return signal_strength
|
||||
|
||||
|
||||
async def cellular_ip():
|
||||
@timeout(3)
|
||||
async def inner():
|
||||
try:
|
||||
await cellular.send_command('AT+IPADDR')
|
||||
except ModemErrorResponse as e:
|
||||
if 'Network not opened' in e.lines[0]:
|
||||
return '0.0.0.0'
|
||||
|
||||
async def cellular_ip() -> str:
|
||||
try:
|
||||
ip = await inner()
|
||||
except uTimeoutError:
|
||||
ip = '0.0.0.0'
|
||||
return ip
|
||||
ip_resp = await cellular.send_command('AT+IPADDR')
|
||||
if ip_resp[0].startswith('+IPADDR: '):
|
||||
return ip_resp[0].strip('+IPADDR: ')
|
||||
except ModemErrorResponse:
|
||||
return '0.0.0.0'
|
||||
|
||||
|
||||
async def cellular_check_service_ready():
|
||||
|
@ -165,10 +172,6 @@ async def cellular_check_service_ready():
|
|||
|
||||
|
||||
async def restart_modem():
|
||||
async def reset():
|
||||
await cellular.send_command('ATZ', require_ok=True)
|
||||
|
||||
await run_with_timeout(func=reset, timeout_sec=2)
|
||||
await asyncio.sleep(0.5)
|
||||
bee_power_pin.value(0)
|
||||
time.sleep(0.5)
|
||||
|
@ -192,8 +195,17 @@ async def cellular_check_connected():
|
|||
@timeout(CELLULAR_STARTUP_TIMEOUT)
|
||||
async def start_modem():
|
||||
while True:
|
||||
if (await run_with_timeout(func=cellular_wake_modem, timeout_sec=30)).failure:
|
||||
logger('Modem wake-up timed out', source='CELL', level=LogLevel.error)
|
||||
failures = -1
|
||||
try:
|
||||
if (await run_with_timeout(func=cellular_wake_modem, timeout_sec=5)).failure:
|
||||
logger('Modem wake-up timed out', source='CELL', level=LogLevel.error)
|
||||
failures += 1
|
||||
if failures == 11:
|
||||
machine.reset()
|
||||
await restart_modem()
|
||||
continue
|
||||
except ModemErrorResponse:
|
||||
# Sporadic ERROR responses
|
||||
await restart_modem()
|
||||
continue
|
||||
|
||||
|
@ -239,24 +251,108 @@ async def start_modem():
|
|||
await restart_modem()
|
||||
continue
|
||||
|
||||
await cellular.send_command(f'AT+CGSOCKCONT=1,"IP","{CELLULAR_APN}"', require_ok=True)
|
||||
await cellular.send_command('AT+CSOCKSETPN=1', require_ok=True)
|
||||
await cellular.send_command('AT+CIPMODE=0', require_ok=True)
|
||||
await cellular.send_command('AT+NETOPEN', require_ok=True)
|
||||
break
|
||||
try:
|
||||
await cellular.send_command(f'AT+CGSOCKCONT=1,"IP","{CELLULAR_APN}"', require_ok=True)
|
||||
await cellular.send_command('AT+CSOCKSETPN=1', require_ok=True)
|
||||
await cellular.send_command('AT+CIPMODE=0', require_ok=True)
|
||||
# await cellular.send_command('AT+CNMP=38', require_ok=True)
|
||||
await cellular.send_command('AT+NETOPEN', require_ok=True)
|
||||
break
|
||||
except ModemErrorResponse as e:
|
||||
print(e)
|
||||
await restart_modem()
|
||||
break
|
||||
|
||||
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')
|
||||
|
||||
logger(f'IP: {await cellular_ip()}', source='CELL')
|
||||
logger(f'Signal strength: {await cellular_signal_strength()}', source='CELL')
|
||||
logger('Modem initialized', source='CELL')
|
||||
|
||||
|
||||
async def cellular_start_http():
|
||||
try:
|
||||
await cellular.send_command('AT+HTTPINIT')
|
||||
return True
|
||||
except ModemErrorResponse:
|
||||
return False
|
||||
|
||||
|
||||
async def start_modem_task():
|
||||
logger('Initalizing modem', source='CELL')
|
||||
while True:
|
||||
try:
|
||||
gc.collect()
|
||||
await start_modem()
|
||||
|
||||
async def inner():
|
||||
while True:
|
||||
try:
|
||||
gc.collect()
|
||||
await start_modem()
|
||||
except uTimeoutError:
|
||||
await asyncio.sleep(10)
|
||||
continue
|
||||
|
||||
if TRACCAR_CONN_MODE == 'http':
|
||||
await asyncio.sleep(0.5)
|
||||
success = False
|
||||
for i in range(30):
|
||||
httpinit = await run_with_timeout(func=cellular_start_http, timeout_sec=5)
|
||||
if httpinit.failure:
|
||||
logger('AT+HTTPINIT timeout', source='CELL', level=LogLevel.error)
|
||||
await restart_modem()
|
||||
continue
|
||||
if not httpinit.result:
|
||||
logger('AT+HTTPINIT failure', source='CELL', level=LogLevel.error)
|
||||
await restart_modem()
|
||||
continue
|
||||
else:
|
||||
success = True
|
||||
if not success:
|
||||
continue
|
||||
|
||||
break
|
||||
except uTimeoutError:
|
||||
await asyncio.sleep(10)
|
||||
|
||||
while True:
|
||||
x = await run_with_timeout(func=inner, timeout_sec=300)
|
||||
if not x.failure:
|
||||
break
|
||||
|
||||
gc.collect()
|
||||
|
||||
await cellular_send_http('http://postman-echo.com/ip', 'get')
|
||||
|
||||
# TODO: loop to reconnect modem
|
||||
|
||||
|
||||
@timeout(10)
|
||||
async def cellular_send_http(url: str, method: str, data: str = None):
|
||||
m = method.upper()
|
||||
if m == 'GET':
|
||||
mode = 0
|
||||
elif m == 'POST':
|
||||
if not data:
|
||||
raise Exception
|
||||
mode = 1
|
||||
else:
|
||||
raise Exception
|
||||
|
||||
await cellular.send_command(f'AT+HTTPPARA="URL","{url}"')
|
||||
_, resp = await cellular.send_command(f'AT+HTTPACTION={mode}', expecing_plus=True)
|
||||
|
||||
_, status_code, data_len = resp.strip('+HTTPACTION: ').split(',')
|
||||
if status_code != '200':
|
||||
logger(f'HTTP {m} failed: {status_code}', source='CELL', level=LogLevel.error)
|
||||
return
|
||||
|
||||
data = await cellular.send_command(f'AT+HTTPREAD={data_len}', read_until=b'+HTTPREAD:0\r\n', clean_lines=False)
|
||||
if data[0] != b'OK\r\n':
|
||||
raise Exception
|
||||
data = list(data)
|
||||
del data[0]
|
||||
del data[0]
|
||||
del data[-1]
|
||||
print(data)
|
||||
|
||||
|
||||
asyncio.run(start_modem_task())
|
||||
|
|
Loading…
Reference in New Issue