# DataRouter 轻量级 C 语言数据路由库。**发送能力和接收能力分开声明**,端口独立设置 send_type 和 recv_type,支持多外设一对多广播路由。 ## 概念 | 术语 | 说明 | |------|------| | **发送能力 (Send Capability)** | 编译期声明的可发送报文类型,生成 `datarouter_send_()` | | **接收能力 (Recv Capability)** | 编译期声明的可接收报文类型,生成 `datarouter_on_recv_()` | | **端口 (Port)** | 运行期连接点,独立设置 send_type + recv_type + handler 列表 | | **Handler** | 用户实现的物理外设发送函数,一个端口可注册多个(默认上限 4) | ## 快速开始 ### 1. 声明能力 创建自己的 `datarouter_config.h`(可参考 `datarouter_config_template.h`): ```c #define DATAROUTER_SEND_CAPABILITIES \ DATAROUTER_SEND(sensor, "Sensor data report") \ DATAROUTER_SEND(status, "Device status report") #define DATAROUTER_RECV_CAPABILITIES \ DATAROUTER_RECV(rtcm, "RTCM correction data") \ DATAROUTER_RECV(command, "Remote control command") ``` > 库默认自带一份示例配置。将你的 `datarouter_config.h` 放到项目目录, > 编译时添加 `-I /path/to/your/config` 即可覆盖。无需修改库源代码。 > > **注意**:确保你的配置目录在包含路径中出现在库目录之前,否则编译 `datarouter.c` > 时仍会使用库的默认配置。在 CMake 中可参考: > ```cmake > # 你的 CMakeLists.txt > include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}) # 全局优先 > add_subdirectory(path/to/DataRouter) > target_link_libraries(my_app DataRouter) > ``` ### 2. 实现外设发送 handler ```c static void uart_send(uint32_t port_id, const void *data, size_t len) { HAL_UART_Transmit(&huart1, data, len, 1000); } static void tcp_send(uint32_t port_id, const void *data, size_t len) { send(tcp_socket, data, len, 0); } ``` ### 3. 创建端口 ```c datarouter_init(); /* —— 只发送:传感器上报 —— */ datarouter_port_t tx = datarouter_port_create(); datarouter_port_set_send_type(tx, DATAROUTER_SEND_sensor); datarouter_port_add_handler(tx, uart_send); datarouter_port_add_handler(tx, tcp_send); datarouter_send_sensor(tx, "temperature:25.3", 16); // → UART + TCP /* —— 只接收:RTCM 修正 —— */ datarouter_port_t rx = datarouter_port_create(); datarouter_port_set_recv_type(rx, DATAROUTER_RECV_rtcm); // 外设收到数据后由用户调回调: datarouter_on_recv_rtcm(rx, data, len); /* —— 同时收发:状态上报 + 命令接收 —— */ datarouter_port_t bi = datarouter_port_create(); datarouter_port_set_send_type(bi, DATAROUTER_SEND_status); datarouter_port_set_recv_type(bi, DATAROUTER_RECV_command); datarouter_port_add_handler(bi, uart_send); datarouter_send_status(bi, "status:OK", 9); datarouter_on_recv_command(bi, "reboot", 6); ``` ### 4. 实现接收回调 ```c void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len) { apply_rtcm_correction(data, len); } void datarouter_on_recv_command(uint32_t port_id, const void *data, size_t len) { execute_command(data, len); } ``` ## API 一览 ### 初始化 ```c void datarouter_init(void); // 幂等初始化 void datarouter_reset(void); // 重置全部状态 ``` ### 端口管理 ```c datarouter_port_t datarouter_port_create(void); // 创建端口 void datarouter_port_delete(datarouter_port_t port); // 删除 void datarouter_port_set_send_type(port, int cap_id); // 设置发送类型 int datarouter_port_get_send_type(port); // -1 = 未设置 void datarouter_port_set_recv_type(port, int cap_id); // 设置接收类型 int datarouter_port_get_recv_type(port); // -1 = 未设置 int datarouter_port_add_handler(port, handler); // 注册外设 handler int datarouter_port_remove_handler(port, handler); // 移除 void datarouter_port_clear_handlers(port); // 清除全部 int datarouter_port_handler_count(port); // 当前数量 ``` ### 发送触发(每个 SEND 能力生成一个) ```c int datarouter_send_sensor(port, data, len); // 0 成功 / -1 未初始化 int datarouter_send_status(port, data, len); // -2 端口无效 // -3 send_type 不匹配 // -4 无 handler ``` ### 接收回调(每个 RECV 能力生成一个声明) ```c void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len); void datarouter_on_recv_command(uint32_t port_id, const void *data, size_t len); ``` 库提供弱符号默认空实现,用户定义同名函数覆盖。 ### 能力元数据(两组独立) ```c int datarouter_send_cap_count(void); const char *datarouter_send_cap_name(int cap_id); const char *datarouter_send_cap_desc(int cap_id); int datarouter_recv_cap_count(void); const char *datarouter_recv_cap_name(int cap_id); const char *datarouter_recv_cap_desc(int cap_id); ``` ## 路由模型 ``` send_sensor(port, data, len) │ ├─→ handler[0] = uart_send → UART ├─→ handler[1] = tcp_send → TCP └─→ handler[2] = can_send → CAN ``` - 一个端口可注册多个 handler(一对多广播) - 同一 handler 可注册到多个端口(多路复用) - 运行时通过 `add_handler` / `remove_handler` 动态改变路由 - 清空 handler 列表后发送返回 -4 ## 编译 ```bash cmake -S . -B build cmake --build build ``` 可选配置: ```bash cmake -DCMAKE_C_FLAGS="-DDATAROUTER_MAX_PORTS=128 -DDATAROUTER_MAX_HANDLERS_PER_PORT=8" ``` ## 测试 ```bash cmake --build build ctest --test-dir build # 或直接运行 ./build/test_datarouter ``` 当前 27 个测试用例,覆盖端口管理、send_type/recv_type 独立设置、handler 增删、一对多广播、接收回调、能力元数据、错误边界。 ## 文件结构 ``` datarouter_config.h 发送 + 接收能力配置(用户编辑) datarouter.h 公共 API + X-macro 展开 datarouter.c 实现(端口表 + handler 遍历) example.c 收发分离使用示例 tests/test_datarouter.c 单元测试(27 用例) DESIGN.md 详细设计文档(含 PlantUML 图) TEST_CASES.md 测试用例文档 ``` ## 依赖 - C11 编译器 - CMake ≥ 3.10 - 无第三方库依赖