Files
templates/python/protocan/README.md
Andrey Kruchinkin 02da823a94 feat(protocan-py): хостовые кодеки ProtoCAN и каталога на Python
Собрано из SETGUI/src/gui_desktop/core (protocan, can_transport, protocol,
gas_catalog); в CAN_to_RS485/template/python лежала такая же копия.

Только stdlib: ни Qt, ни pyserial — модулям передают bytes, порт и
таймауты остаются делом вызывающего кода. Кодировщики совпадают побайтово
с c/protocan-transport, что зафиксировано эталонами в его тестах.

Добавлен __init__.py: gas_catalog импортирует protocol относительным
импортом, без пакета копия в CAN_to_RS485/template не собиралась.
2026-08-23 01:15:36 +03:00

58 lines
2.8 KiB
Markdown
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.
# 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/protocan-transport/tests/test_transport.c`.
## Быстрый старт
```python
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())
```
Каталог регистров:
```python
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`, здесь — источник истины.