will try to redo back
This commit is contained in:
Generated
-2
@@ -2,7 +2,5 @@
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/../thirdparty/imgui" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/../thirdparty/implot" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
+86
-26
@@ -6,11 +6,51 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(OpenGL_GL_PREFERENCE GLVND)
|
||||
|
||||
# Define file paths for thirdparty modules
|
||||
set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/imgui)
|
||||
set(IMPLOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/implot)
|
||||
# ==============================================================================
|
||||
# ЗАГРУЗКА ЗАВИСИМОСТЕЙ ЧЕРЕЗ FETCHCONTENT (ImGui и ImPlot)
|
||||
# ==============================================================================
|
||||
include(FetchContent)
|
||||
|
||||
# Find Required Packages
|
||||
# 1. Загрузка Dear ImGui
|
||||
FetchContent_Declare(
|
||||
imgui
|
||||
GIT_REPOSITORY https://github.com/ocornut/imgui.git
|
||||
GIT_TAG master
|
||||
)
|
||||
FetchContent_MakeAvailable(imgui)
|
||||
|
||||
# 2. Загрузка ImPlot
|
||||
FetchContent_Declare(
|
||||
implot
|
||||
GIT_REPOSITORY https://github.com/epezent/implot.git
|
||||
GIT_TAG master
|
||||
)
|
||||
FetchContent_MakeAvailable(implot)
|
||||
|
||||
# ==============================================================================
|
||||
# НАСТРОЙКА ИСХОДНЫХ КОДОВ БИБЛИОТЕК
|
||||
# ==============================================================================
|
||||
# Исходники ImGui
|
||||
set(IMGUI_SOURCES
|
||||
${imgui_SOURCE_DIR}/imgui.cpp
|
||||
${imgui_SOURCE_DIR}/imgui_demo.cpp
|
||||
${imgui_SOURCE_DIR}/imgui_draw.cpp
|
||||
${imgui_SOURCE_DIR}/imgui_tables.cpp
|
||||
${imgui_SOURCE_DIR}/imgui_widgets.cpp
|
||||
${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp
|
||||
${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp
|
||||
)
|
||||
|
||||
# Исходники ImPlot
|
||||
set(IMPLOT_SOURCES
|
||||
${implot_SOURCE_DIR}/implot.cpp
|
||||
${implot_SOURCE_DIR}/implot_items.cpp
|
||||
${implot_SOURCE_DIR}/implot_demo.cpp
|
||||
)
|
||||
|
||||
# ==============================================================================
|
||||
# ПОИСК СИСТЕМНЫХ ПАКЕТОВ
|
||||
# ==============================================================================
|
||||
find_package(PkgConfig REQUIRED)
|
||||
find_package(OpenGL REQUIRED)
|
||||
pkg_check_modules(GLFW REQUIRED glfw3)
|
||||
@@ -18,25 +58,9 @@ pkg_check_modules(LIBSERIALPORT REQUIRED IMPORTED_TARGET libserialport)
|
||||
find_package(Protobuf REQUIRED)
|
||||
find_package(gRPC REQUIRED)
|
||||
|
||||
# ImGUI things
|
||||
set(IMGUI_SOURCES
|
||||
${IMGUI_DIR}/imgui.cpp
|
||||
${IMGUI_DIR}/imgui_demo.cpp
|
||||
${IMGUI_DIR}/imgui_draw.cpp
|
||||
${IMGUI_DIR}/imgui_tables.cpp
|
||||
${IMGUI_DIR}/imgui_widgets.cpp
|
||||
${IMGUI_DIR}/backends/imgui_impl_glfw.cpp
|
||||
${IMGUI_DIR}/backends/imgui_impl_opengl3.cpp
|
||||
)
|
||||
|
||||
set(IMPLOT_SOURCES
|
||||
${IMPLOT_DIR}/implot.cpp
|
||||
${IMPLOT_DIR}/implot_items.cpp
|
||||
${IMPLOT_DIR}/implot_demo.cpp
|
||||
sources/SerialApp.cpp
|
||||
include/SerialApp.h
|
||||
)
|
||||
|
||||
# ==============================================================================
|
||||
# ГЕНЕРАЦИЯ PROTOBUF & GRPC
|
||||
# ==============================================================================
|
||||
set(proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/service.pb.cc")
|
||||
set(proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/service.pb.h")
|
||||
set(grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/service.grpc.pb.cc")
|
||||
@@ -65,9 +89,14 @@ target_include_directories(proto_lib PUBLIC
|
||||
${Protobuf_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# ==============================================================================
|
||||
# СБОРКА ОСНОВНОГО ПРИЛОЖЕНИЯ
|
||||
# ==============================================================================
|
||||
add_executable(${PROJECT_NAME} main.cpp
|
||||
${IMGUI_SOURCES}
|
||||
${IMPLOT_SOURCES}
|
||||
sources/SerialApp.cpp
|
||||
include/SerialApp.h
|
||||
sources/ConnectionWindow.cpp
|
||||
include/ConnectionWindow.h
|
||||
sources/PayloadWindow.cpp
|
||||
@@ -80,9 +109,9 @@ target_include_directories(${PROJECT_NAME} PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${Protobuf_INCLUDE_DIRS}
|
||||
${IMGUI_DIR}
|
||||
${IMGUI_DIR}/backends
|
||||
${IMPLOT_DIR}
|
||||
${imgui_SOURCE_DIR}
|
||||
${imgui_SOURCE_DIR}/backends
|
||||
${implot_SOURCE_DIR}
|
||||
${GLFW_INCLUDE_DIRS}
|
||||
${OPENGL_INCLUDE_DIR}
|
||||
)
|
||||
@@ -98,3 +127,34 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
)
|
||||
|
||||
configure_file(style/dracula.theme ${CMAKE_CURRENT_BINARY_DIR}/dracula.theme COPYONLY)
|
||||
|
||||
|
||||
#Является частой практикой в больших проектах для поддержки
|
||||
#единой схемы данныхмежду сервером и клиентом.
|
||||
#Если .proto лежит в отдельном Git-репозитории на сервере
|
||||
#лучше использовать FetchContent. Он корректно кэширует файлы
|
||||
#и обновляет их только при смене тега или хэша коммита.
|
||||
#```
|
||||
#FetchContent_Declare(
|
||||
#remote_proto
|
||||
#GIT_REPOSITORY git@your-server.com:shared/protocols.git # URL вашего репозитория
|
||||
#GIT_TAG main # Ветка, тег или хэш коммита
|
||||
#)
|
||||
#FetchContent_MakeAvailable(remote_proto)
|
||||
#```
|
||||
#Теперь файл доступен по пути: ${remote_proto_SOURCE_DIR}/service.proto
|
||||
#
|
||||
#не забыть обновить команду компиляции Protobuf,
|
||||
#заменив локальные пути на пути из FetchContent:
|
||||
#```
|
||||
#add_custom_command(
|
||||
#OUTPUT "${proto_srcs}" "${proto_hdrs}" "${grpc_srcs}" "${grpc_hdrs}"
|
||||
#COMMAND ${Protobuf_PROTOC_EXECUTABLE}
|
||||
#ARGS --grpc_out="${CMAKE_CURRENT_BINARY_DIR}"
|
||||
#--cpp_out="${CMAKE_CURRENT_BINARY_DIR}"
|
||||
#-I "${remote_proto_SOURCE_DIR}" # Корневая папка для импортов
|
||||
#--plugin=protoc-gen-grpc=/usr/bin/grpc_cpp_plugin
|
||||
#"${REMOTE_PROTO_PATH}" # Сам файл
|
||||
#DEPENDS "${REMOTE_PROTO_PATH}"
|
||||
#)
|
||||
#```
|
||||
|
||||
@@ -17,54 +17,67 @@ static void glfw_error_callback(int error, const char* description) {
|
||||
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
|
||||
}
|
||||
|
||||
// Простейшая реализация вашего сервиса gRPC (для примера)
|
||||
bool initImGUI(GLFWwindow *&window) {
|
||||
glfwSetErrorCallback(glfw_error_callback);
|
||||
if (!glfwInit()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
window = glfwCreateWindow(1280, 720, "Serial App", nullptr, nullptr);
|
||||
if (window == nullptr) {
|
||||
return true;
|
||||
}
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSwapInterval(1);
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
const ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 130");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Простейшая реализация сервиса gRPC
|
||||
class MyServiceImpl final : public serial_sample::Greeter::Service {
|
||||
grpc::Status SayHello(grpc::ServerContext* context,
|
||||
const serial_sample::HelloRequest* request,
|
||||
serial_sample::HelloReply* reply) override {
|
||||
std::cout << request->name() << std::endl;
|
||||
reply->set_message("Hello, " + request->name() + "!");
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int, char**) {
|
||||
glfwSetErrorCallback(glfw_error_callback);
|
||||
if (!glfwInit()) return 1;
|
||||
GLFWwindow *window;
|
||||
if (initImGUI(window)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "Serial App", nullptr, nullptr);
|
||||
if (window == nullptr) return 1;
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSwapInterval(1);
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 130");
|
||||
|
||||
SerialApp app;
|
||||
SerialApp app; // frontend manager
|
||||
app.initialize();
|
||||
|
||||
// === НАЧАЛО ИНИЦИАЛИЗАЦИИ gRPC СЕРВЕРА ===
|
||||
std::string server_address("0.0.0.0:50051");
|
||||
MyServiceImpl grpc_service;
|
||||
// инициализация gRPC
|
||||
const std::string serverAddress("0.0.0.0:50051");
|
||||
MyServiceImpl serviceImpl;
|
||||
|
||||
grpc::ServerBuilder builder;
|
||||
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
|
||||
builder.RegisterService(&grpc_service);
|
||||
builder.AddListeningPort(serverAddress, grpc::InsecureServerCredentials());
|
||||
builder.RegisterService(&serviceImpl);
|
||||
|
||||
std::unique_ptr<grpc::Server> grpc_server(builder.BuildAndStart());
|
||||
std::cout << "gRPC Server listening on " << server_address << std::endl;
|
||||
std::unique_ptr gRPCServer(builder.BuildAndStart());
|
||||
std::cout << "gRPC Server listening on " << serverAddress << std::endl;
|
||||
|
||||
// Запускаем сервер в фоновом потоке
|
||||
std::thread grpc_thread([&grpc_server]() {
|
||||
grpc_server->Wait(); // Блокирует фоновый поток, пока сервер работает
|
||||
// сервер стартует в фоновом БЛОКИРУЮЩЕМ потоке
|
||||
std::thread gRPCThread([&gRPCServer] {
|
||||
gRPCServer->Wait();
|
||||
});
|
||||
// =========================================
|
||||
|
||||
@@ -82,9 +95,9 @@ int main(int, char**) {
|
||||
}
|
||||
|
||||
ImGui::Render();
|
||||
int display_w, display_h;
|
||||
glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||
glViewport(0, 0, display_w, display_h);
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(window, &width, &height);
|
||||
glViewport(0, 0, width, height);
|
||||
glClearColor(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
@@ -92,14 +105,14 @@ int main(int, char**) {
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
|
||||
// === КОРРЕКТНОЕ ВЫКЛЮЧЕНИЕ gRPC СЕРВЕРА ===
|
||||
// выключение gRPC
|
||||
std::cout << "Shutting down gRPC server..." << std::endl;
|
||||
// Останавливаем сервер (это разблокирует метод Wait() в фоновом потоке)
|
||||
grpc_server->Shutdown();
|
||||
gRPCServer->Shutdown();
|
||||
|
||||
// Обязательно дожидаемся завершения фонового потока перед выходом из main
|
||||
if (grpc_thread.joinable()) {
|
||||
grpc_thread.join();
|
||||
if (gRPCThread.joinable()) {
|
||||
gRPCThread.join();
|
||||
}
|
||||
std::cout << "gRPC server thread joined." << std::endl;
|
||||
// =========================================
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
/**
|
||||
* @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);
|
||||
}
|
||||
Reference in New Issue
Block a user