12 KiB
SET protocol v2 — wire contract
1. Назначение
SETP v2 — единственный прикладной протокол новых устройств SET. Он решает три задачи одним контрактом:
- запросы и ответы: конфигурация, диагностика, журналы и общая карта данных;
- события: значения для отрисовки в реальном времени;
- обновление прошивки с продолжением после разрыва соединения.
Носитель не меняет типы сообщений или payload. Меняется только способ доставки целого SETP-кадра.
2. Общий кадр
offset size field
0 2 SOF = A5 5A
2 1 version = 02
3 1 flags
4 2 message_type u16 LE
6 2 source u16 LE
8 2 destination u16 LE
10 2 sequence u16 LE
12 2 payload_length u16 LE
14 N payload
14+N 4 CRC32 IEEE u32 LE
CRC32 считается от version (offset 2) до последнего байта payload. Полином
0xEDB88320, init/final XOR 0xFFFFFFFF; проверочное значение строки
123456789 — 0xCBF43926.
Максимальный payload базового профиля — 512 байт. Реализация может объявить
меньший предел через CAPABILITIES, но не может молча принять начало большого
кадра и отбросить его конец.
Эталонный PING к узлу 0x002A, sequence 0x1234, с ACK_REQUIRED:
A5 5A 02 08 01 00 00 00 2A 00 34 12 00 00 33 EC 33 04
3. Флаги и транзакции
| Бит | Имя | Смысл |
|---|---|---|
| 0 | RESPONSE |
ответ; тип и sequence повторяют запрос |
| 1 | EVENT |
самостоятельная публикация, не ответ |
| 2 | ERROR |
status ответа не равен OK |
| 3 | ACK_REQUIRED |
отправитель требует явный ответ |
| 4 | MORE |
за этим логическим куском последуют другие |
| 5 | PRIORITY |
приоритет над обычной телеметрией |
| 7..6 | — | передавать нулями |
Запрос содержит RESPONSE=0, EVENT=0. Ответ содержит RESPONSE=1, тот же
message_type и sequence, а первые два байта payload всегда являются
status u16. Push-телеметрия содержит EVENT=1; её sequence — счётчик
кадров источника и позволяет заметить потерю.
source/destination = 0 означает локальный узел в точке-точке. 0xFFFF —
broadcast; на broadcast-запрос отвечать нельзя, если прикладная команда явно
не задаёт безопасное окно ответа.
4. Стабильные типы сообщений
| Диапазон | Назначение |
|---|---|
0x0000..0x00FF |
системные команды и карта данных |
0x0100..0x01FF |
обновление прошивки |
0x0200..0x0FFF |
зарезервировано общей спецификацией |
0x1000..0x7FFF |
команды конкретного изделия |
0x8000..0xFFFF |
зарезервировано |
Общие команды:
| Код | Имя | Назначение |
|---|---|---|
0x0001 |
PING |
доступность и uptime |
0x0002 |
DEVICE_INFO |
модель, версии, серийный номер |
0x0003 |
CAPABILITIES |
интерфейсы, MTU, функции, лимиты |
0x0008 |
DIAGNOSTICS |
счётчики транспорта и приложения |
0x0009 |
READ |
чтение 32-битно адресуемой карты |
0x000A |
WRITE |
транзакционная запись карты |
0x0010 |
LOG_READ |
чтение журналов блоками |
0x0011 |
CATALOG |
метаданные общей карты |
0x0012 |
SUBSCRIBE |
создать/изменить поток данных |
0x0013 |
PUBLISH |
пакет значений для отрисовки |
0x0014 |
UNSUBSCRIBE |
удалить подписку |
0x0100..0105 |
FW_* |
обновление и активация прошивки |
Неизвестный тип не является ошибкой кадрирования. Устройство отвечает
UNSUPPORTED, если запрос был адресован ему и требовал ответа.
5. Телеметрия реального времени
SUBSCRIBE
subscription_id u16
period_ms u32 (0 = по изменению)
address_count u16
addresses u32[address_count]
Ответ сообщает status и фактически принятый период. Устройство вправе увеличить
слишком короткий период. Подписка принадлежит соединению/источнику и удаляется
при его закрытии либо командой UNSUBSCRIBE.
PUBLISH
subscription_id u16
sample_sequence u16
timestamp_ms u32
item_count u16
repeat item_count times:
address u32
encoding u8 (U16/I16/U32/I32/F32/BYTES)
element_count u8
data_length u16
data u8[data_length]
timestamp_ms — монотонное время устройства. GUI строит графики по нему, а не
по моменту прихода в Windows. Большой массив, например спектр, разбивается на
несколько PUBLISH с MORE; адрес и sample_sequence остаются теми же.
Телеметрия имеет меньший приоритет, чем ответы и прошивка. При переполнении
очереди разрешено отбросить старый PUBLISH, но нельзя частично передать кадр.
6. Прошивка
Типы:
| Код | Команда |
|---|---|
0x0100 |
FW_BEGIN |
0x0101 |
FW_DATA |
0x0102 |
FW_END |
0x0103 |
FW_ABORT |
0x0104 |
FW_STATUS |
0x0105 |
FW_ACTIVATE |
FW_BEGIN содержит размер, CRC32 и SHA-256 образа, версию, базовый адрес,
целевой слот, желаемый размер блока, ID ключа и необязательную подпись. Подпись
проверяется над каноническим manifest, а не над полученными по частям данными:
ASCII "SETPFW2\0" || image_size || image_crc32 || image_version ||
base_address || slot || sha256
Числа manifest также little-endian. Рекомендуемая подпись — Ed25519 (64 байта).
Конкретный загрузчик может потребовать подписанный образ и вернуть AUTH_FAILED
для неподписанного.
FW_DATA:
offset u32 | data_length u16 | flags u16 | data_crc32 u32 | data[]
Ответ возвращает status и next_offset u32. Повтор уже записанного блока с теми
же данными обязан быть идемпотентным. После потери связи GUI запрашивает
FW_STATUS и продолжает с next_offset.
FW_END повторяет размер, CRC32 и SHA-256. Устройство проверяет весь образ и
только затем переводит слот в READY. FW_ACTIVATE меняет загрузочный слот;
операция обновления не должна перезаписывать единственный рабочий образ. Для
серийных устройств требуется A/B или эквивалентный механизм rollback.
CRC32 защищает линию, SHA-256 — целостность образа, подпись — происхождение. Один CRC не является защитой от подмены прошивки.
7. Привязки к физическим интерфейсам
RS-232, RS-485, USB CDC
Кадры передаются подряд как поток байтов. Parser обязан восстанавливаться после
мусора и битого CRC. На RS-485 используются source/destination; передача
broadcast не должна запускать прошивку или запись конфигурации.
Ethernet TCP
TCP несёт тот же поток кадров без дополнительной длины: она уже есть в header.
Один recv() может вернуть часть кадра или несколько кадров. Порт по умолчанию
задаётся приложением; рекомендуемое значение проекта — 25060, оно не считается
зарегистрированным IANA. Для внешних сетей используется TLS, SETP внутри TLS не
меняется.
Ethernet UDP
Одна UDP-датаграмма содержит ровно один полный SETP-кадр. Датаграммы с хвостом,
двумя кадрами или несовпадающей длиной отбрасываются. Базовый payload 512 байт
не превышает безопасный IPv4 MTU. Прошивка по UDP допустима только в режиме
stop-and-wait с ACK_REQUIRED; предпочтителен TCP.
CAN
Через классический CAN передаются байты того же полного SETP-кадра. Повторно кодировать команды в поля CAN ID нельзя.
Extended CAN ID:
28..24 prefix = 0x12
23..16 destination (младшие 8 бит SETP destination)
15..8 source (младшие 8 бит SETP source)
7 priority
6..0 channel
CAN-профиль использует node 1..254; 0 и 255 сохраняют смысл local и
broadcast. Поля полного SETP-заголовка остаются обязательными и должны совпасть
с CAN ID после reassembly.
PCI классического CAN:
FIRST: data[0]=0x10, data[1..2]=total_length u16 LE, data[3..7]=5 байт
CONSECUTIVE: data[0]=0x20|SN, data[1..7]=до 7 байт, SN начинается с 1
FLOW_CONTROL:data[0]=0x30|status, data[1]=block_size, data[2]=st_min_ms
status: 0 continue, 1 wait, 2 overflow. Номер сегмента идёт по модулю 16.
Timeout сборки по умолчанию 500 мс. Новый FIRST заменяет незавершённую сборку
того же канала. CAN-FD может увеличить данные сегмента в следующей версии
binding, не меняя SETP frame/message/payload.
8. Совместимость
GUI protocol v1 и SETP v2 несовместимы. Автоопределение допускается только во время миграции: клиент посылает v2 PING, затем при полном тайм-ауте пробует v1. После первого корректного ответа формат соединения фиксируется до отключения. Новое устройство не должно одновременно публиковать v1 и v2 в одном потоке.