|
|
@ -3,7 +3,6 @@ |
|
|
|
import os |
|
|
|
import os |
|
|
|
import usb1 |
|
|
|
import usb1 |
|
|
|
import time |
|
|
|
import time |
|
|
|
import json |
|
|
|
|
|
|
|
import subprocess |
|
|
|
import subprocess |
|
|
|
from typing import List, NoReturn |
|
|
|
from typing import List, NoReturn |
|
|
|
from functools import cmp_to_key |
|
|
|
from functools import cmp_to_key |
|
|
@ -24,51 +23,6 @@ def get_expected_signature(panda: Panda) -> bytes: |
|
|
|
cloudlog.exception("Error computing expected signature") |
|
|
|
cloudlog.exception("Error computing expected signature") |
|
|
|
return b"" |
|
|
|
return b"" |
|
|
|
|
|
|
|
|
|
|
|
def read_panda_logs(panda: Panda) -> None: |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
Forward panda logs to the cloud |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
params = Params() |
|
|
|
|
|
|
|
serial = panda.get_usb_serial() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log_state = {} |
|
|
|
|
|
|
|
try: |
|
|
|
|
|
|
|
ls = params.get("PandaLogState") |
|
|
|
|
|
|
|
if ls is not None: |
|
|
|
|
|
|
|
l = json.loads(ls) |
|
|
|
|
|
|
|
for k, v in l.items(): |
|
|
|
|
|
|
|
if isinstance(k, str) and isinstance(v, int): |
|
|
|
|
|
|
|
log_state[k] = v |
|
|
|
|
|
|
|
except (TypeError, json.JSONDecodeError): |
|
|
|
|
|
|
|
cloudlog.exception("failed to parse PandaLogState") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
try: |
|
|
|
|
|
|
|
if serial in log_state: |
|
|
|
|
|
|
|
logs = panda.get_logs(last_id=log_state[serial]) |
|
|
|
|
|
|
|
else: |
|
|
|
|
|
|
|
logs = panda.get_logs(get_all=True) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# truncate logs to 100 entries if needed |
|
|
|
|
|
|
|
MAX_LOGS = 100 |
|
|
|
|
|
|
|
if len(logs) > MAX_LOGS: |
|
|
|
|
|
|
|
cloudlog.warning(f"Panda {serial} has {len(logs)} logs, truncating to {MAX_LOGS}") |
|
|
|
|
|
|
|
logs = logs[-MAX_LOGS:] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# update log state |
|
|
|
|
|
|
|
if len(logs) > 0: |
|
|
|
|
|
|
|
log_state[serial] = logs[-1]["id"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for log in logs: |
|
|
|
|
|
|
|
if log['timestamp'] is not None: |
|
|
|
|
|
|
|
log['timestamp'] = log['timestamp'].isoformat() |
|
|
|
|
|
|
|
cloudlog.event("panda_log", **log, serial=serial) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
params.put("PandaLogState", json.dumps(log_state)) |
|
|
|
|
|
|
|
except Exception: |
|
|
|
|
|
|
|
cloudlog.exception(f"Error getting logs for panda {serial}") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def flash_panda(panda_serial: str) -> Panda: |
|
|
|
def flash_panda(panda_serial: str) -> Panda: |
|
|
|
try: |
|
|
|
try: |
|
|
|
panda = Panda(panda_serial) |
|
|
|
panda = Panda(panda_serial) |
|
|
@ -191,8 +145,6 @@ def main() -> NoReturn: |
|
|
|
params.put_bool("PandaHeartbeatLost", True) |
|
|
|
params.put_bool("PandaHeartbeatLost", True) |
|
|
|
cloudlog.event("heartbeat lost", deviceState=health, serial=panda.get_usb_serial()) |
|
|
|
cloudlog.event("heartbeat lost", deviceState=health, serial=panda.get_usb_serial()) |
|
|
|
|
|
|
|
|
|
|
|
read_panda_logs(panda) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if first_run: |
|
|
|
if first_run: |
|
|
|
if panda.is_internal(): |
|
|
|
if panda.is_internal(): |
|
|
|
# update time from RTC |
|
|
|
# update time from RTC |
|
|
|