docs: добавь поясняющие комментарии к модулям и инструментам
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
# Сегментация кадров SETProtocol v2 в classic CAN: первый пакет несёт длину и пять байт
|
||||
# данных, последующие — номер и до семи байт. Сборщик обслуживает один источник и канал;
|
||||
# таймаут или нарушение последовательности сбрасывает неполный кадр.
|
||||
|
||||
"""Classic-CAN segmentation for canonical SETProtocol v2 frames."""
|
||||
|
||||
from __future__ import annotations
|
||||
@@ -90,6 +94,8 @@ def segment(packet: bytes, address: CanAddress) -> list[CanFrame]:
|
||||
+ packet[:FIRST_DATA_SIZE],
|
||||
)
|
||||
]
|
||||
# Номер занимает младшую тетраду PCI и циклически переходит 15 -> 0.
|
||||
# Он проверяет порядок фрагментов, но не является полным номером блока.
|
||||
sequence = 1
|
||||
for offset in range(FIRST_DATA_SIZE, len(packet), CONSECUTIVE_DATA_SIZE):
|
||||
chunk = packet[offset : offset + CONSECUTIVE_DATA_SIZE]
|
||||
@@ -115,6 +121,8 @@ class CanReassembler:
|
||||
self._next_sequence = 1
|
||||
|
||||
def feed(self, frame: CanFrame, now_ms: int) -> bytes | None:
|
||||
# now_ms должен поступать из одной монотонной шкалы времени клиента.
|
||||
# Таймаут относится к интервалу между принятыми сегментами.
|
||||
if self._can_id is not None and now_ms >= self._deadline_ms:
|
||||
self.reset()
|
||||
raise SetProtocolError("таймаут сборки SETProtocol CAN")
|
||||
@@ -125,6 +133,8 @@ class CanReassembler:
|
||||
total = int.from_bytes(frame.data[1:3], "little")
|
||||
if not HEADER_SIZE + CRC_SIZE <= total <= FRAME_MAX:
|
||||
raise SetProtocolError("неверная полная длина SETP CAN")
|
||||
# FIRST начинает новую сборку, заменяя ранее накопленный хвост.
|
||||
# Сохраняем полный CAN ID, чтобы не смешать источники и каналы.
|
||||
self._buffer = bytearray(frame.data[3:])
|
||||
self._expected_length = total
|
||||
self._can_id = frame.can_id
|
||||
@@ -151,6 +161,8 @@ class CanReassembler:
|
||||
self._deadline_ms = now_ms + self.timeout_ms
|
||||
if len(self._buffer) != self._expected_length:
|
||||
return None
|
||||
# Создаём независимый неизменяемый результат до сброса контекста.
|
||||
# Проверка согласованности адресов ниже уже не удерживает сборку.
|
||||
packet = bytes(self._buffer)
|
||||
can_id = self._can_id
|
||||
self.reset()
|
||||
@@ -167,6 +179,8 @@ class CanReassembler:
|
||||
or priority != address.priority
|
||||
):
|
||||
raise SetProtocolError("SETP header не совпадает с CAN ID")
|
||||
# Здесь проверена транспортная сборка. CRC самого SET-кадра
|
||||
# проверяет следующий слой декодирования протокола.
|
||||
return packet
|
||||
if pci == PCI_FLOW_CONTROL:
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user