# DataRouter 轻量级 C 语言数据路由库。**发送能力和接收能力分开声明**,端口绑定 `send_type` 和外设 handler 列表。调用 `dr_send_(data, len)` 时自动广播到所有匹配端口。 ## 概念 | 术语 | 说明 | |------|------| | **发送能力 (Send Capability)** | 编译期声明的可发送报文类型,生成 `dr_send_(data, len)` | | **接收能力 (Recv Capability)** | 编译期声明的可接收报文类型,生成 `dr_on_recv_(port, data, len)` | | **端口 (Port)** | 运行期创建的连接点,包含 `send_type` + handler 列表 | | **Handler** | 用户实现的物理外设发送函数,一个端口可注册多个(默认上限 4) | ## 快速开始 ### 1. 声明能力 创建自己的 `dr_config.h`(可参考 `dr_config_template.h`): ```c #define DR_SEND_CAPABILITIES \ DR_SEND(sensor, "Sensor data report") \ DR_SEND(status, "Device status report") #define DR_RECV_CAPABILITIES \ DR_RECV(rtcm, "RTCM correction data") \ DR_RECV(command, "Remote control command") ``` > 库自带默认配置。将你的 `dr_config.h` 放到项目目录, > 编译时添加 `-I /path/to/your/config` 即可覆盖。无需修改库源码。 > > ```cmake > 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 dr_init(); /* —— 传感器上报:sensor 报文走 UART + TCP —— */ dr_port_t tx = dr_port_create(); dr_port_set_send_type(tx, DR_SEND_sensor); dr_port_add_handler(tx, uart_send); dr_port_add_handler(tx, tcp_send); /* 不指定端口,库自动广播到所有 send_type=sensor 的端口 */ dr_send_sensor("temperature:25.3", 16); // → UART + TCP /* —— 接收:实现回调,外设数据到达后自行调用 —— */ dr_on_recv_rtcm(rx_port, data, len); ``` ### 4. 实现接收回调 ```c void dr_on_recv_rtcm(uint32_t port_id, const void *data, size_t len) { apply_rtcm_correction(data, len); } ``` ## API 一览 ### 初始化 ```c void dr_init(void); // 幂等初始化 void dr_reset(void); // 重置全部状态 ``` ### 端口管理 ```c dr_port_t dr_port_create(void); // 创建端口 void dr_port_delete(dr_port_t port); // 删除 void dr_port_set_send_type(port, int cap_id); // 设置发送类型 int dr_port_get_send_type(port); // -1 = 未设置 int dr_port_add_handler(port, handler); // 注册外设 handler int dr_port_remove_handler(port, handler); // 移除 void dr_port_clear_handlers(port); // 清除全部 int dr_port_handler_count(port); // 当前数量 ``` ### 发送触发(每个 SEND 能力生成一个) ```c int dr_send_sensor(const void *data, size_t len); // 0 成功 int dr_send_status(const void *data, size_t len); // -1 未初始化 // -2 无匹配端口 ``` 不指定端口,库遍历所有端口,`send_type` 匹配的逐一调用其全部 handler。 ### 接收回调(每个 RECV 能力生成一个声明) ```c void dr_on_recv_rtcm(uint32_t port_id, const void *data, size_t len); void dr_on_recv_command(uint32_t port_id, const void *data, size_t len); ``` 库提供弱符号默认空实现,用户定义同名函数覆盖。 ### 能力元数据(两组独立) ```c int dr_send_cap_count(void); const char *dr_send_cap_name(int cap_id); const char *dr_send_cap_desc(int cap_id); int dr_recv_cap_count(void); const char *dr_recv_cap_name(int cap_id); const char *dr_recv_cap_desc(int cap_id); ``` ## 路由模型 ``` dr_send_sensor("temperature:25.3", 16) │ ├─→ port 0 (send_type=sensor) handlers[0]=uart_send → UART │ handlers[1]=tcp_send → TCP └─→ port 1 (send_type=sensor) handlers[0]=can_send → CAN ``` - 调用 `send_(data, len)` 时,库遍历所有端口,自动匹配 `send_type` - 每个端口可注册多个 handler(一对多广播) - 同一 handler 可注册到多个端口(多路复用) - 运行时通过 `add_handler` / `remove_handler` / `port_delete` 动态改变路由 - 无任何端口匹配该 `send_type` 时返回 -2 ## 编译 ```bash cmake -S . -B build cmake --build build ``` 可选配置: ```bash cmake -DCMAKE_C_FLAGS="-DDR_MAX_PORTS=128 -DDR_MAX_HANDLERS_PER_PORT=8" ``` ## 嵌入式 / Cortex-M 构建 库支持 `arm-none-eabi-gcc` 交叉编译,提供 **7 个 CMake preset** 覆盖常见 Cortex-M 目标: ```bash # 列出所有 preset cmake --list-presets # Cortex-M3(软浮点) cmake --preset cm3 cmake --build --preset cm3 # Cortex-M4F(硬件浮点,单精度) cmake --preset cm4-hard cmake --build --preset cm4-hard # Cortex-M7F(硬件浮点,双精度) cmake --preset cm7-hard-dp cmake --build --preset cm7-hard-dp ``` > 使用 preset 编译需要 `arm-none-eabi-gcc` 在 PATH 中。 > 各 preset 均启用 `DR_SOURCE_ONLY` 模式——只提供源文件路径, > 你需要将 `datarouter.c` 加入自己的 target 以继承项目编译标志: ```cmake # 你的 CMakeLists.txt set(DR_SOURCE_ONLY ON) FetchContent_MakeAvailable(datarouter) target_sources(my_app PRIVATE ${datarouter_SOURCE_DIR}/datarouter.c) target_include_directories(my_app PRIVATE ${datarouter_SOURCE_DIR}) ``` ### 编译兼容性矩阵 启用 `DR_COMPILE_CHECK` 可自动检测 `arm-none-eabi-gcc` 并对 CM3/CM4/CM7 各变体执行编译验证: ```bash cmake -B build-check -DDR_COMPILE_CHECK=ON cmake --build build-check # 生成 check_cm3, check_cm4-hard, … 等 target # 或单独检查某个变体: make check_cm7-hard-dp ``` ### 内置 CMake Preset 列表 | Preset | 目标 | FPU | ABI | |--------|------|-----|-----| | `cm3` | Cortex-M3 | 无 | soft | | `cm4-soft` | Cortex-M4 | 无 | soft | | `cm4-hard` | Cortex-M4F | FPv4-SP-D16 | hard | | `cm7-soft` | Cortex-M7 | 无 | soft | | `cm7-hard-sp` | Cortex-M7F | FPv5-SP-D16 | hard | | `cm7-hard-dp` | Cortex-M7F | FPv5-D16 | hard | ## 测试 ```bash cmake --build build ctest --test-dir build # 或直接运行 ./build/test_datarouter ``` 当前 22 个测试用例,覆盖端口管理、send_type 与 handler 设置、自动广播路由、接收回调、能力元数据。 ## 文件结构 ``` dr_config.h 发送 + 接收能力配置(用户可覆盖) datarouter.h 公共 API + X-macro 展开 datarouter.c 实现(端口表 + send 遍历) dr_config_template.h 外部配置模板 example.c 使用示例 tests/test_datarouter.c 单元测试(22 用例) DESIGN.md 详细设计文档(含 PlantUML 图) TEST_CASES.md 测试用例文档 ``` ## 依赖 - C11 编译器 - CMake ≥ 3.10 - 无第三方库依赖