61 lines
2.9 KiB
Python
61 lines
2.9 KiB
Python
# Исторический регистровый CAN-протокол BALZAM/TMS2812. Формат идентификаторов и порядок слов
|
|
# относятся именно к этому профилю; общий физический CAN не делает его совместимым с SET v2
|
|
# или протоколом ПМ35.
|
|
|
|
"""GUI-neutral adapter for the shared templates Balsam 167 CAN decoder."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from protocan import balsam
|
|
|
|
from protocan import protocan as pc
|
|
from .shared_protocol import get_shared_protocol
|
|
|
|
|
|
def decode(raw_id: int, data: bytes, *, ide: bool = True,
|
|
rtr: bool = False) -> pc.Decoded | None:
|
|
if not ide or rtr or not balsam.is_balsam_id(raw_id):
|
|
return None
|
|
try:
|
|
frame = balsam.decode(raw_id, data, native=get_shared_protocol())
|
|
except ValueError as error:
|
|
result = pc.Decoded(pc.ProtoCanId.parse(raw_id), len(data), bytes(data),
|
|
ide=ide, rtr=rtr, protocol="BALZAM 167")
|
|
result.summary = "BALZAM: неверный кадр"
|
|
result.fields = [("Протокол", "BALZAM 167"), ("Ошибка", str(error))]
|
|
result.warnings.append(str(error))
|
|
return result
|
|
if frame is None:
|
|
return None
|
|
|
|
pid = pc.ProtoCanId(
|
|
raw=frame.can_id, body=frame.start_address, msg_type=0,
|
|
device=frame.device, device_type=0,
|
|
pm=1 if frame.from_device else 0, priority=0,
|
|
)
|
|
result = pc.Decoded(pid, len(data), bytes(data), ide=ide, rtr=rtr,
|
|
protocol="BALZAM 167", device_label=frame.device_name,
|
|
message_label=("BALZAM данные" if frame.from_device
|
|
else "BALZAM команды"))
|
|
result.summary = frame.summary
|
|
result.fields = [
|
|
("Протокол", "BALZAM 167 legacy eCAN"),
|
|
("Узел", "%d — %s" % (frame.device, frame.device_name)),
|
|
("Направление", frame.route),
|
|
("Отправитель", frame.device_name if frame.from_device else "ПМ"),
|
|
("Получатель", "ПМ" if frame.from_device else frame.device_name),
|
|
("Начальный адрес", "0x%04X" % frame.start_address),
|
|
("Маска трёх слов", "0b%s" % format(frame.present_mask, "03b")),
|
|
]
|
|
result.registers = [(item.address, item.value) for item in frame.registers]
|
|
for item in frame.registers:
|
|
result.fields.append((
|
|
"0x%04X %s" % (item.address, item.name or "регистр"),
|
|
"0x%04X (%d)" % (item.value, item.signed_value),
|
|
))
|
|
if not frame.from_device and item.address == 0x7F:
|
|
result.fields.append(("Команды ПМ", frame.command_description(item.value)))
|
|
if frame.present_mask == 0:
|
|
result.warnings.append("В адресном слове не отмечен ни один регистр")
|
|
return result
|