Files
templates/python/set_devices/balsam_can.py
Andrey a5e46d4627 Расширить обмен по шинам, CAN-адаптеры и обработку графиков
Добавить очереди операций PBUS/SBUS, общую консоль, настройки Candle и SLCAN, декодеры DSView и обработку плотных графиков. Обновить протокол Бальзам и проверки общих компонентов.
2026-10-17 14:36:14 +03:00

61 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Исторический регистровый 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.sender_name, # Все CAN ID 167 подписываются источником: команды — TMS, ответы — именем устройства из таблицы адресов.
message_label=("BALZAM Heartbeat" if frame.is_heartbeat else "BALZAM данные" if frame.from_device # Тип сообщения явно выделяет heartbeat по адресу и маске, сохраняя имя отправителя.
else "BALZAM команды"))
result.summary = frame.summary
result.fields = [
("Протокол", "BALZAM 167 legacy eCAN"),
("Узел", "%d — %s" % (frame.device, frame.device_name)),
("Направление", frame.route),
("Отправитель", frame.sender_name), # Используем ту же подпись источника, что в маршруте и имени кадра любого устройства 167.
("Получатель", frame.recipient_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.value if frame.is_heartbeat else item.signed_value), # Счётчик секунд и идентификаторы heartbeat беззнаковые, в отличие от технологических int16.
))
if item.address == 0x7F:
result.fields.append(("Активные биты Commands", frame.command_description(item.value)))
if frame.present_mask == 0:
result.warnings.append("В адресном слове не отмечен ни один регистр")
return result