65 lines
1.8 KiB
Python
65 lines
1.8 KiB
Python
import sys, os
|
|
from threading import Thread
|
|
from queue import Queue, Empty
|
|
|
|
_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
if _root not in sys.path:
|
|
sys.path.insert(0, _root)
|
|
|
|
from backend.a_backend import ABackend
|
|
from a_transceiver import ATransceiver
|
|
from msg.container import MsgContainer
|
|
|
|
|
|
class SerialBackend(ABackend):
|
|
"""Backend that reads from a serial (COM / tty) port."""
|
|
|
|
def __init__(self, port: str, baud_rate: int = 115200):
|
|
self._port = port
|
|
self._baud = baud_rate
|
|
self._serial = None
|
|
self._xcvr = None
|
|
self._running = False
|
|
self._queue: Queue = Queue()
|
|
self._thread = Thread(target=self._run, daemon=True)
|
|
|
|
def register_xcvr(self, xcvr):
|
|
self._xcvr = xcvr
|
|
xcvr.on_register(self)
|
|
|
|
def send(self, xcvr: ATransceiver, data: bytes):
|
|
self._queue.put(data)
|
|
|
|
def connect(self):
|
|
import serial
|
|
self._serial = serial.Serial(self._port, self._baud, timeout=0.1)
|
|
self._running = True
|
|
|
|
def start(self):
|
|
self._thread.start()
|
|
|
|
def stop(self):
|
|
self._running = False
|
|
if self._thread.is_alive():
|
|
self._thread.join(timeout=2.0)
|
|
|
|
def disconnect(self):
|
|
if self._serial and self._serial.is_open:
|
|
self._serial.close()
|
|
|
|
def _run(self):
|
|
while self._running:
|
|
try:
|
|
data = self._serial.read(64)
|
|
if data and self._xcvr:
|
|
self._xcvr.on_recv(MsgContainer(data, self._xcvr))
|
|
# Drain outgoing queue
|
|
while True:
|
|
try:
|
|
self._serial.write(self._queue.get_nowait())
|
|
except Empty:
|
|
break
|
|
except Exception:
|
|
self._running = False
|
|
break
|