Skip to content

Commit 0dadccf

Browse files
authored
Support USB Debugger (#448)
* Added `SOBD`. (#447) * Implemented `update()`. (#447) * Exported `SOBD`. (#447) * Added authentication. (#447) * Package reorganized. (#447)
1 parent ac1fdce commit 0dadccf

3 files changed

Lines changed: 83 additions & 0 deletions

File tree

leads_comm_serial/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@
55

66
from leads_comm_serial.connection import *
77
from leads_comm_serial.identity import *
8+
from leads_comm_serial.sobd import *

leads_comm_serial/sobd/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from leads_comm_serial.sobd import *

leads_comm_serial/sobd/sobd.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from typing import Literal as _Literal, override as _override
2+
3+
from serial import Serial as _Serial
4+
5+
from leads import require_config as _require_config, Device as _Device, L as _L
6+
from leads.comm import Entity as _Entity, Callback as _Callback, Service as _Service
7+
from leads_comm_serial.connection import SerialConnection
8+
from leads_comm_serial.identity import AutoIdentity
9+
10+
11+
class SOBD(_Device, _Entity, AutoIdentity):
12+
def __init__(self, port: str | _Literal["auto"], baud_rate: int = 9600, password: str = "") -> None:
13+
_Device.__init__(self)
14+
_Entity.__init__(self, -1, _SOBDCallback(self))
15+
AutoIdentity.__init__(self, port == "auto")
16+
self._serial: _Serial = _Serial()
17+
self._serial.baudrate = baud_rate
18+
self._connection: SerialConnection | None = None
19+
self._serial.port = self.suggest_next_port() if port == "auto" else port
20+
self._password: str = password
21+
self._locked: bool = password != ""
22+
23+
@_override
24+
def port(self) -> str:
25+
return self._serial.port
26+
27+
@_override
28+
def initialize(self, *parent_tags: str) -> None:
29+
super().initialize(*parent_tags)
30+
self.start(True)
31+
32+
@_override
33+
def update(self, data: str) -> None:
34+
if data.startswith("pwd="):
35+
if data[4:] != self._password:
36+
self.close()
37+
else:
38+
self._locked = False
39+
if self._locked:
40+
return
41+
if data.startswith("dbl="):
42+
_require_config().w_debug_level = data[4:].upper()
43+
else:
44+
self.write("\n".join(_L.history_messages()).encode())
45+
46+
@_override
47+
def check_identity(self, connection: SerialConnection) -> bool:
48+
connection.send(b"ic")
49+
return (msg := connection.receive()) and msg.startswith(self.tag().encode())
50+
51+
@_override
52+
def run(self) -> None:
53+
self._callback.on_initialize(self)
54+
self._connection = self.establish_connection(self._serial)
55+
self._callback.on_connect(self, self._connection)
56+
self._stage(self._connection)
57+
58+
@_override
59+
def write(self, payload: bytes) -> None:
60+
if not self._connection:
61+
raise IOError("Target must be connected to perform this operation")
62+
self._connection.send(payload)
63+
64+
@_override
65+
def close(self) -> None:
66+
if self._connection:
67+
self._connection.close()
68+
69+
70+
class _SOBDCallback(_Callback):
71+
def __init__(self, sobd: SOBD) -> None:
72+
super().__init__()
73+
self._sobd: SOBD = sobd
74+
75+
@_override
76+
def on_receive(self, service: _Service, msg: bytes) -> None:
77+
self.super(service=service, msg=msg)
78+
try:
79+
self._sobd.update(msg.decode())
80+
except UnicodeDecodeError:
81+
_L.debug(f"Discarding this message: {msg}")

0 commit comments

Comments
 (0)