Files
templates/c/set-protocol/PROTOCOL.md

12 KiB
Raw Blame History

SET protocol v2 — wire contract

1. Назначение

SETP v2 — единственный прикладной протокол новых устройств SET. Он решает три задачи одним контрактом:

  1. запросы и ответы: конфигурация, диагностика, журналы и общая карта данных;
  2. события: значения для отрисовки в реальном времени;
  3. обновление прошивки с продолжением после разрыва соединения.

Носитель не меняет типы сообщений или 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; проверочное значение строки 1234567890xCBF43926.

Максимальный 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 в одном потоке.