Files
templates/python/protocan/README.md
T
Andrey 876b58517c feat(set-protocol): Раздели GAS и добавь пакетный сбор регистров
Сохрани адресацию отдельных регистров GAS 0x3 и выдели слотам тип 0x4 с маской Word0. Добавь единое C-ядро GAS_WATCH2, тонкие Python/JNI-порты и проверки общих эталонных байтов.

Совместимость: тип 0x4 больше не обслуживает Modbus Coil. Потребителям PCAN_MSG_MODBUS_COIL и ProtoCanMsgToModbusCoil нужно перейти на GAS_SLOT и отдельный API слотов; регистровый GAS остаётся на 0x3.
2026-10-23 14:14:48 +03:00

3.3 KiB

protocan (Python)

Хостовая сторона протоколов: разбор сообщений ProtoCAN, транспортный кадр моста CAN↔RS485 и кодеки каталога общего адресного пространства.

Только stdlib, Python 3.9+. Ни Qt, ни pyserial: модули не открывают порт и не знают, откуда пришли байты, — им передают bytes. Поэтому они проверяются обычными host-тестами и одинаково работают в GUI, в скрипте и в CI.

Состав

Модуль Что делает Зеркало на C
protocan.py разбор 29-битного идентификатора и тела всех типов сообщений в человекочитаемый вид pcan_id.c
transport.py кадр AA 55 … CRC16, потоковый разборщик с ресинхронизацией, CRC-16/CCITT-FALSE pcan_frame.c
protocol.py кадр A5 5A протокола SETGUI: сборка, разбор, CRC32 gui_frame.c
gas_catalog.py каталог регистров с именами и подписка на поток значений gui_catalog.c

Зависимость внутри пакета одна: gas_catalog использует protocol. Остальные модули независимы.

Кодировщики C и Python дают побайтово одинаковый результат — это зафиксировано эталонами в c/set-protocol/tests/test_transport.c.

Быстрый старт

from protocan import protocan, transport

parser = transport.FrameParser()

for frame in parser.feed(port.read(256)):          # bytes из любого источника
    print(protocan.decode(frame.can_id, frame.data).summary)

port.write(transport.build_frame(0x18FF0102, b"\x01\x02").encode())

Каталог регистров:

from protocan.gas_catalog import ObjectEntry, ObjectType, encode_entry, decode_entry

entry = ObjectEntry(address=0x0100, type=ObjectType.U16, flags=0,
                    scale_pow10=-1, unit=0, name="Температура")
raw = encode_entry(entry)
assert decode_entry(raw) == entry

Границы

Разбор отделён от ввода-вывода намеренно: порт, таймауты и переподключение — дело вызывающего кода. Байты внутрь, объекты наружу.

Проверено в проектах

SETGUI (вкладки «Шина CAN» и «Адресное пространство»), CAN_to_RS485. Там пакет лежит внутри gui_desktop/core, здесь — источник истины.

GAS: регистры 0x3 и слоты 0x4

Адресация GAS: 0x3 — отдельные 16-битные регистры 0…65535, запись 1…4 слов. 0x4 — слот с Word0-маской и тремя значениями; PERIPH сохраняет 200 слов в 67 слотах 0xMM00…0xMM42. Формат определяется MsgType, без настройки профиля.