Добавить протокол DEIF, диагностику CAN и сохранение сессий

This commit is contained in:
2026-10-04 23:34:26 +03:00
parent 6c08eece61
commit 0e3d89e1ee
8 changed files with 321 additions and 47 deletions

View File

@@ -23,6 +23,8 @@ from .qt_compat import QObject, Signal
_EXTENDED_ID = 0x80000000
_FRAME_RECEIVE = 1
_FRAME_ECHO = 2
_FRAME_ERROR = 3
_MODE_LISTEN_ONLY = 0x0001
@@ -160,6 +162,8 @@ class CandleAdapter(QObject):
frame_received = Signal(int, bytes)
capture_received = Signal(int, bytes, bool, bool)
transmit_echo = Signal(int, bytes, bool, bool)
bus_error = Signal(int, bytes, int)
connection_lost = Signal(str)
def __init__(self, parent: QObject | None = None) -> None:
@@ -223,7 +227,7 @@ class CandleAdapter(QObject):
self._reader = None
self._listen_only = False
def send(self, can_id: int, data: bytes) -> None:
def send(self, can_id: int, data: bytes, *, extended: bool = True) -> None:
device = self._device
if device is None:
raise CandleError("Candle-адаптер не подключён")
@@ -232,7 +236,9 @@ class CandleAdapter(QObject):
if len(data) > 8:
raise CandleError("Classic CAN поддерживает не более 8 байт")
frame = _Frame()
frame.can_id = (can_id & 0x1FFFFFFF) | _EXTENDED_ID
if not 0 <= can_id <= (0x1FFFFFFF if extended else 0x7FF):
raise CandleError("CAN ID вне диапазона")
frame.can_id = can_id | (_EXTENDED_ID if extended else 0)
frame.can_dlc = len(data)
frame.channel = self._channel
frame.data[:len(data)] = data
@@ -250,13 +256,22 @@ class CandleAdapter(QObject):
frame = _Frame()
if not api.dll.candle_frame_read(device, ct.byref(frame), 50):
continue
if (api.dll.candle_frame_type(ct.byref(frame)) == _FRAME_RECEIVE
and frame.channel == self._channel):
size = min(frame.can_dlc, 8)
if frame.channel != self._channel:
continue
kind = api.dll.candle_frame_type(ct.byref(frame))
size = min(frame.can_dlc, 8)
data = bytes(frame.data[:size])
if kind == _FRAME_ERROR or frame.flags & 0x01:
self.bus_error.emit(frame.can_id & 0x1FFFFFFF if kind == _FRAME_ERROR else 0,
data, frame.flags)
if kind == _FRAME_ECHO:
self.transmit_echo.emit(api.dll.candle_frame_id(ct.byref(frame)), data,
bool(frame.can_id & 0x80000000), bool(frame.can_id & 0x40000000))
elif kind == _FRAME_RECEIVE:
self.capture_received.emit(api.dll.candle_frame_id(ct.byref(frame)),
bytes(frame.data[:size]), bool(frame.can_id & 0x80000000), bool(frame.can_id & 0x40000000))
data, bool(frame.can_id & 0x80000000), bool(frame.can_id & 0x40000000))
self.frame_received.emit(api.dll.candle_frame_id(ct.byref(frame)),
bytes(frame.data[:size]))
data)
def close(self) -> None:
self.disconnect_channel()