305 lines
14 KiB
Protocol Buffer
305 lines
14 KiB
Protocol Buffer
/**
|
||
* @file serial.proto
|
||
* @brief Протокол обмена между GUI‑клиентом и backend‑службой
|
||
* для работы с последовательным (UART/RS‑232/USB‑CDC) портом.
|
||
*
|
||
* Протокол построен на базе **Protocol Buffers 3** и **gRPC**.
|
||
* Он покрывает все типичные задачи:
|
||
* - перечисление доступных портов;
|
||
* - открытие/закрытие порта с полным набором параметров;
|
||
* - отправку и приём произвольных пакетов;
|
||
* - ведение журнала (лог‑стрим) всех переданных/полученных байтов
|
||
* – удобно для отладки и верификации протокола.
|
||
*
|
||
* Файл снабжён Doxygen‑комментариями, поэтому из него можно
|
||
* автоматически получить красивую HTML‑/PDF‑документацию.
|
||
*/
|
||
syntax = "proto3";
|
||
|
||
package serial;
|
||
|
||
/* -------------------------------------------------------------------------- */
|
||
/* Enums – вспомогательные типы */
|
||
/* -------------------------------------------------------------------------- */
|
||
|
||
/**
|
||
* @enum Parity
|
||
* @brief Возможные варианты чётности (parity) при работе с UART.
|
||
*
|
||
* Имена полностью совпадают с теми, что использует библиотека **pyserial**
|
||
* (и, в принципе, большинство C/C++‑библиотек для последовательных портов).
|
||
*/
|
||
enum Parity {
|
||
PARITY_NONE = 0; /// Без чётности.
|
||
PARITY_EVEN = 1; /// Чётность чётных битов.
|
||
PARITY_ODD = 2; /// Чётность нечётных битов.
|
||
PARITY_MARK = 3; /// Маркер (всегда 1).
|
||
PARITY_SPACE= 4; /// Пробел (всегда 0).
|
||
}
|
||
|
||
/**
|
||
* @enum StopBits
|
||
* @brief Конфигурация стоп‑битов.
|
||
*
|
||
* Значения соответствуют типичным настройкам UART‑контроллера.
|
||
*/
|
||
enum StopBits {
|
||
STOPBITS_ONE = 0; /// Один стоп‑бит.
|
||
STOPBITS_ONE_POINT_FIVE = 1; /// Полтора стоп‑бита (реже используется).
|
||
STOPBITS_TWO = 2; /// Два стоп‑бита.
|
||
}
|
||
|
||
/**
|
||
* @enum StatusCode
|
||
* @brief Универсальный набор кодов возврата для большинства RPC‑методов.
|
||
*
|
||
* При необходимости можно добавить новые коды, но текущего набора достаточно
|
||
* для базовых сценариев.
|
||
*/
|
||
enum StatusCode {
|
||
OK = 0; /// Операция выполнена успешно.
|
||
INVALID_ARGUMENT = 1; /// Переданы некорректные аргументы (например, отрицательная скорость).
|
||
NOT_FOUND = 2; /// Запрашиваемый объект (порт, файл и т.п.) не найден.
|
||
INTERNAL_ERROR = 3; /// Внутренняя ошибка сервера (исключение, недоступный ресурс).
|
||
NOT_CONNECTED = 4; /// Операция невозможна, т.к. порт не открыт.
|
||
}
|
||
|
||
/* -------------------------------------------------------------------------- */
|
||
/* Сообщения – описание данных, передаваемых по gRPC */
|
||
/* -------------------------------------------------------------------------- */
|
||
|
||
/**
|
||
* @message SerialDevice
|
||
* @brief Информация об одном последовательном порте, доступном в системе.
|
||
*
|
||
* @param port_name Системное имя порта (например, «COM3», «/dev/ttyUSB0»).
|
||
* @param description Человекочитаемое описание, если ОС его предоставляет.
|
||
* @param hardware_id Строка‑идентификатор устройства (VID/PID и т.п.).
|
||
*/
|
||
message SerialDevice {
|
||
string port_name = 1;
|
||
string description = 2;
|
||
string hardware_id = 3;
|
||
}
|
||
|
||
/**
|
||
* @message SerialConfig
|
||
* @brief Полный набор параметров, необходимый для открытия последовательного порта.
|
||
*
|
||
* @param port_name Должно совпадать с `SerialDevice.port_name`.
|
||
* @param baud_rate Скорость в бодах (например, 9600, 115200 …).
|
||
* @param data_bits Количество битов данных (5‑8, обычно 8).
|
||
* @param parity Чётность (см. enum @ref Parity).
|
||
* @param stop_bits Стоп‑биты (см. enum @ref StopBits).
|
||
* @param packet_size Фиксированный размер полезной нагрузки пакета.
|
||
* 0 → размер произвольный (по умолчанию).
|
||
*/
|
||
message SerialConfig {
|
||
string port_name = 1;
|
||
uint32 baud_rate = 2;
|
||
uint32 data_bits = 3;
|
||
Parity parity = 4;
|
||
StopBits stop_bits = 5;
|
||
uint32 packet_size = 6;
|
||
}
|
||
|
||
/**
|
||
* @message ConfigResponse
|
||
* @brief Ответ на запрос `Open`/`Close`. Содержит статус операции и,
|
||
* при ошибке, человекочитаемое сообщение.
|
||
*
|
||
* @param status Код статуса (см. enum @ref StatusCode).
|
||
* @param error Текстовое пояснение, заполнено только если `status != OK`.
|
||
*/
|
||
message ConfigResponse {
|
||
StatusCode status = 1;
|
||
string error = 2;
|
||
}
|
||
|
||
/**
|
||
* @message Packet
|
||
* @brief Описание логической "пакетной" единицы, которую GUI отправляет
|
||
* на backend, а backend – в последовательный порт.
|
||
*
|
||
* Полезная нагрузка (`payload`) передаётся «как есть» (raw‑bytes).
|
||
*
|
||
* @param seq_id Последовательный номер пакета, генерируется клиентом.
|
||
* Удобен для отладки и согласования запрос‑ответ.
|
||
* @param payload Бинарные данные, которые действительно окажутся на линии.
|
||
* @param tags Необязательная карта «ключ → значение», используемая
|
||
* только внутри программы (не попадает в кадр UART).
|
||
*/
|
||
message Packet {
|
||
uint64 seq_id = 1;
|
||
bytes payload = 2;
|
||
map<string, string> tags = 3;
|
||
}
|
||
|
||
/**
|
||
* @message SendResponse
|
||
* @brief Ответ на RPC `SendPacket`. Содержит статус, сообщение об ошибке и
|
||
* «эхо‑идентификатор», позволяющий клиенту убедиться, что ответ
|
||
* относится к конкретному запросу.
|
||
*
|
||
* @param status Код статуса (см. enum @ref StatusCode).
|
||
* @param error Текстовое описание ошибки (если есть).
|
||
* @param echo_seq_id Идентификатор пакета, пришедший в запросе.
|
||
*/
|
||
message SendResponse {
|
||
StatusCode status = 1;
|
||
string error = 2;
|
||
uint64 echo_seq_id = 3;
|
||
}
|
||
|
||
/**
|
||
* @message SerialLogEntry
|
||
* @brief Описание одного события (TX или RX) на уровне сырых байтов.
|
||
*
|
||
* Это «протокол‑верификация»: каждая запись сохраняется в журнал
|
||
* и может быть передана клиенту в реальном времени.
|
||
*
|
||
* @param dir Направление трафика (TX – передача, RX – приём).
|
||
* @param timestamp Время события в миллисекундах с начала эпохи Unix.
|
||
* @param raw_data Точные байты, полученные/отправленные в этом событии.
|
||
* @param note Необязательная строка‑комментарий (например,
|
||
* «checksum ok», «frame start», …).
|
||
*/
|
||
message SerialLogEntry {
|
||
/** @brief Направление трафика. */
|
||
enum Direction {
|
||
/** @brief Пакет был отправлен в порт. */
|
||
TX = 0;
|
||
/** @brief Пакет был получен из порта. */
|
||
RX = 1;
|
||
}
|
||
Direction dir = 1;
|
||
uint64 timestamp = 2;
|
||
bytes raw_data = 3;
|
||
string note = 4;
|
||
}
|
||
|
||
/**
|
||
* @message LogStreamRequest
|
||
* @brief Параметры подписки на поток журнала.
|
||
*
|
||
* @param from_start Если true – клиент получает *все* накопленные записи,
|
||
* иначе – только новые, появившиеся после установления
|
||
* соединения.
|
||
*/
|
||
message LogStreamRequest {
|
||
bool from_start = 1;
|
||
}
|
||
|
||
/**
|
||
* @message DeviceList
|
||
* @brief Обёртка, возвращающая список найденных последовательных портов.
|
||
*
|
||
* @param devices Список `SerialDevice`.
|
||
*/
|
||
message DeviceList {
|
||
repeated SerialDevice devices = 1;
|
||
}
|
||
|
||
/* -------------------------------------------------------------------------- */
|
||
/* Service definition – набор RPC‑методов, которые реализует backend */
|
||
/* -------------------------------------------------------------------------- */
|
||
|
||
/**
|
||
* @service SerialService
|
||
* @brief gRPC‑сервис, предоставляющий весь функционал работы с
|
||
* последовательным портом и журналированием.
|
||
*
|
||
* Каждый метод описан ниже, вместе с его параметрами и возвращаемыми
|
||
* типами.
|
||
*/
|
||
service SerialService {
|
||
|
||
// ----------------------------------------------------------------------
|
||
// Device discovery
|
||
// ----------------------------------------------------------------------
|
||
/**
|
||
* @brief Возвращает список всех последовательных портов, обнаруженных в системе.
|
||
*
|
||
* @param request Пустое сообщение (`google.protobuf.Empty`).
|
||
* @return `DeviceList` – массив `SerialDevice`.
|
||
*/
|
||
rpc ListDevices (google.protobuf.Empty) returns (DeviceList);
|
||
|
||
// ----------------------------------------------------------------------
|
||
// Connection handling
|
||
// ----------------------------------------------------------------------
|
||
/**
|
||
* @brief Открывает (или переоткрывает) последовательный порт с указанными
|
||
* параметрами.
|
||
*
|
||
* @param cfg Полный набор параметров соединения (`SerialConfig`).
|
||
* @return `ConfigResponse` – статус операции.
|
||
*/
|
||
rpc Open (SerialConfig) returns (ConfigResponse);
|
||
|
||
/**
|
||
* @brief Закрывает текущий открытый порт (если он был открыт).
|
||
*
|
||
* @param request Пустое сообщение.
|
||
* @return `ConfigResponse` – статус операции.
|
||
*/
|
||
rpc Close (google.protobuf.Empty) returns (ConfigResponse);
|
||
|
||
/**
|
||
* @brief Возвращает конфигурацию, с которой в данный момент открыт порт.
|
||
*
|
||
* Если порт закрыт, возвращается пустой `SerialConfig`.
|
||
*
|
||
* @param request Пустое сообщение.
|
||
* @return `SerialConfig`.
|
||
*/
|
||
rpc GetCurrentConfig (google.protobuf.Empty) returns (SerialConfig);
|
||
|
||
// ----------------------------------------------------------------------
|
||
// Packet transmission
|
||
// ----------------------------------------------------------------------
|
||
/**
|
||
* @brief Отправка одного пакета в открытый последовательный порт.
|
||
*
|
||
* Если в `SerialConfig.packet_size` задан фиксированный размер, то
|
||
* длина `payload` должна строго соответствовать этому размеру.
|
||
*
|
||
* @param pkt Пакет для отправки (`Packet`).
|
||
* @return `SendResponse` – результат записи в порт.
|
||
*/
|
||
rpc SendPacket (Packet) returns (SendResponse);
|
||
|
||
/**
|
||
* @brief Получить один пакет из входящего буфера.
|
||
*
|
||
* Если буфер пуст, сервер возвращает gRPC‑ошибку `NOT_FOUND`.
|
||
*
|
||
* @param request Пустое сообщение.
|
||
* @return `Packet` (или ошибка).
|
||
*/
|
||
rpc ReceivePacket (google.protobuf.Empty) returns (Packet);
|
||
|
||
// ----------------------------------------------------------------------
|
||
// Logging / protocol verification
|
||
// ----------------------------------------------------------------------
|
||
/**
|
||
* @brief Прямо вставить произвольную запись в журнал.
|
||
*
|
||
* Полезно для отладки: можно «симулировать» приходящие данные,
|
||
* не взаимодействуя с реальным оборудованием.
|
||
*
|
||
* @param entry Запись журнала (`SerialLogEntry`).
|
||
* @return Пустое сообщение (`google.protobuf.Empty`).
|
||
*/
|
||
rpc LogRaw (SerialLogEntry) returns (google.protobuf.Empty);
|
||
|
||
/**
|
||
* @brief Подписка на поток всех событий журнала (TX и RX).
|
||
*
|
||
* Поток остаётся открытым до тех пор, пока клиент не отменит RPC.
|
||
*
|
||
* @param req Параметры подписки (`LogStreamRequest`).
|
||
* @return Поток `SerialLogEntry`.
|
||
*/
|
||
rpc StreamLog (LogStreamRequest) returns (stream SerialLogEntry);
|
||
} |