# DataRouter 详细设计文档 ## 1. 设计目标 轻量级 C 语言数据路由库。发送与接收能力分开声明,每个端口独立设置发送类型和接收类型,支持多外设一对多广播路由。 ### 核心设计 ``` DATAROUTER_SEND_CAPABILITIES DATAROUTER_RECV_CAPABILITIES DATAROUTER_SEND(sensor, ...) DATAROUTER_RECV(rtcm, ...) DATAROUTER_SEND(status, ...) DATAROUTER_RECV(command, ...) │ │ ▼ ▼ send_sensor(port, data) on_recv_rtcm(port, data) send_status(port, data) on_recv_command(port, data) │ (用户实现回调) ▼ 端口校验 → for each handler(port, data) │ ┌────────┼────────┐ ▼ ▼ ▼ UART TCP CAN ``` **关键区别**:sensor 只声明发送,不生成接收回调;rtcm 只声明接收,不生成发送函数。端口可独立设置 send_type 和 recv_type,互不干扰。 ### 设计原则 | 原则 | 说明 | |------|------| | 收发分离 | 发送能力和接收能力在配置中分开声明,按需组合 | | 编译期确定能力 | 所有能力在 `datarouter_config.h` 中声明,库自动生成代码 | | 运行期绑定外设 | 端口创建后,通过 `add_handler` 注册物理外设发送函数 | | 一对多广播 | 一个端口可注册多个 handler,发送时逐一调用 | | 不关心物理外设 | 库不依赖任何外设 API,只调用用户提供的 handler | | 零动态内存 | 纯静态数组,无 malloc/free | --- ## 2. 整体架构 ### 2.1 模块依赖 ```plantuml @startuml left to right direction rectangle "用户代码" as User { component "应用逻辑" as App component "datarouter_config.h\n声明发送+接收能力" as Cfg component "外设 handler\nUART / TCP / CAN" as Handlers component "接收回调\n处理收到的报文" as Callbacks } database "DataRouter 库" as Lib { component "datarouter.h\n公共 API + X-macro 展开" as Hdr component "datarouter.c\n端口表 + handler 遍历" as Impl } App --> Hdr Cfg --> Hdr Impl --> Cfg Handlers --> Impl : 注册 handler Callbacks --> Impl : 实现 on_recv_ @enduml ``` ### 2.2 文件结构 | 文件 | 职责 | |------|------| | `datarouter_config.h` | 分别声明 `SEND_CAPABILITIES` 和 `RECV_CAPABILITIES` | | `datarouter.h` | 公共 API + X-macro 展开(两组枚举 + 声明) | | `datarouter.c` | 端口表 + handler 列表遍历 + 弱符号回调 | | `example.c` | 收发分离示例 | | `tests/test_datarouter.c` | 27 个单元测试 | --- ## 3. 收发分离设计 ### 3.1 配置声明 ```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") ``` ### 3.2 展开产物 ``` DATAROUTER_SEND_CAPABILITIES 展开: enum: DATAROUTER_SEND_sensor = 0, DATAROUTER_SEND_status = 1, DATAROUTER_SEND_CAP_COUNT = 2 发送函数: int datarouter_send_sensor(port, data, len); int datarouter_send_status(port, data, len); 元数据: send_names[] = {"sensor", "status"} send_descs[] = {"Sensor data report", "Device status report"} DATAROUTER_RECV_CAPABILITIES 展开: enum: DATAROUTER_RECV_rtcm = 0, DATAROUTER_RECV_command = 1, DATAROUTER_RECV_CAP_COUNT = 2 接收回调: void datarouter_on_recv_rtcm(port, data, len); void datarouter_on_recv_command(port, data, len); 弱符号默认: 每个回调提供空的 weak 实现,用户覆盖 元数据: recv_names[] = {"rtcm", "command"} recv_descs[] = {"RTCM correction data", "Remote control command"} ``` ### 3.3 端口组合示例 ``` 端口 A: send_type = sensor, recv_type = -1 → 只发送 端口 B: send_type = -1, recv_type = rtcm → 只接收 端口 C: send_type = status, recv_type = command → 同时收发 端口 D: send_type = -1, recv_type = -1 → 无功能 ``` --- ## 4. X-macro 代码生成 ### 4.1 展开流程 ```plantuml @startuml == datarouter.h:4 次展开 == -> datarouter_config.h: 获得两组宏列表 datarouter.h -> "第 1 遍": #define DATAROUTER_SEND(id,desc) DATAROUTER_SEND_##id, DATAROUTER_SEND_CAPABILITIES → 发送 enum datarouter.h -> "第 2 遍": #define DATAROUTER_RECV(id,desc) DATAROUTER_RECV_##id, DATAROUTER_RECV_CAPABILITIES → 接收 enum datarouter.h -> "第 3 遍": #define DATAROUTER_SEND(id,desc) int datarouter_send_##id(...); DATAROUTER_SEND_CAPABILITIES → 发送函数声明 datarouter.h -> "第 4 遍": #define DATAROUTER_RECV(id,desc) void datarouter_on_recv_##id(...); DATAROUTER_RECV_CAPABILITIES → 接收回调声明 == datarouter.c:4 次展开 == datarouter.c -> "第 5 遍": 弱符号回调默认实现(DATAROUTER_RECV 展开) datarouter.c -> "第 6 遍": 发送函数实现 body(DATAROUTER_SEND 展开) 校验 → 遍历 handler 列表 datarouter.c -> "第 7 ~ 8 遍": send_names[] / send_descs[] recv_names[] / recv_descs[] @enduml ``` --- ## 5. 数据结构 ### 5.1 核心数据类型 ```plantuml @startuml skinparam classAttributeIconSize 0 enum "datarouter_send_cap" as S { SENSOR STATUS SEND_CAP_COUNT } enum "datarouter_recv_cap" as R { RTCM COMMAND RECV_CAP_COUNT } class "port_entry_t" as Entry { - int send_type - int recv_type - datarouter_send_handler_t handlers[] - int count - uint8_t in_use } class "datarouter_send_handler_t" as Handler { + void (*)(uint32_t port_id, const void *data, size_t len) } class "发送函数" as Send { + int send_sensor(port, data, len) + int send_status(port, data, len) } class "接收回调" as Recv { + void on_recv_rtcm(port, data, len) ← 用户实现 + void on_recv_command(port, data, len) } Entry --> S : send_type ∈ S enum / -1 Entry --> R : recv_type ∈ R enum / -1 Entry --> Handler : handlers[] 数组 Send --> Entry : 校验 send_type + 遍历 handlers Recv --> Entry : 用户根据业务调对应回调 @enduml ``` ### 5.2 `port_entry_t` ```c #define DATAROUTER_MAX_HANDLERS_PER_PORT 4 // 每端口最多 4 个外设 typedef struct { int send_type; // DATAROUTER_SEND_xxx / -1 int recv_type; // DATAROUTER_RECV_xxx / -1 datarouter_send_handler_t handlers[DATAROUTER_MAX_HANDLERS_PER_PORT]; int count; // 当前 handler 数量 uint8_t in_use; } port_entry_t; ``` ### 5.3 端口表 ```c #define DATAROUTER_MAX_PORTS 64 static port_entry_t ports[DATAROUTER_MAX_PORTS]; static uint8_t initialized; ``` --- ## 6. API 参考 ### 6.1 初始化 ```c void datarouter_init(void); // 幂等初始化 void datarouter_reset(void); // 重置全部状态 ``` ### 6.2 端口管理 ```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); // 数量 ``` ### 6.3 发送触发函数(每个 SEND 能力生成一个) ```c int datarouter_send_sensor(port, data, len); int datarouter_send_status(port, data, len); ``` 返回值:0 成功 / -1 未初始化 / -2 端口无效 / -3 send_type 不匹配 / -4 无 handler ### 6.4 接收回调(每个 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); ``` 库提供弱符号默认空实现,用户定义同名函数覆盖。 ### 6.5 能力元数据(两组独立) ```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); ``` --- ## 7. 核心流程 ### 7.1 发送流程 ```plantuml @startuml actor "应用" as App participant "datarouter_send_sensor()" as Send participant "端口表" as Table participant "handlers[]" as HList participant "外设" as Dev App -> Send : send_sensor(port=2, data, len) group 校验 Send -> Send : initialized? alt 否 → return -1 end Send -> Table : ports[2].in_use? alt 否 → return -2 end Send -> Table : ports[2].send_type == SENSOR? alt 否 → return -3 end Send -> Table : ports[2].count > 0? alt 否 → return -4 end end loop for each handler in ports[2].handlers[] Send -> HList : handlers[i](port, data, len) HList -> Dev : 实际外设写入 end Send --> App : return 0 @enduml ``` ### 7.2 接收流程 ```plantuml @startuml actor "外设" as Dev participant "用户分发代码" as Dispatch participant "on_recv_rtcm()" as Callback Dev -> Dispatch : 收到数据,识别为 rtcm 类型 Dispatch -> Callback : on_recv_rtcm(port_id, data, len) Callback --> Dispatch : void @enduml ``` ### 7.3 端口生命周期 ```plantuml @startuml state "空闲" as Idle state "已创建\nsend=-1 recv=-1" as Created state "已配置" as Config [*] --> Idle : reset / 启动 Idle --> Created : port_create() Created --> Config : set_send_type / set_recv_type / add_handler Config --> Config : 独立切换 send_type / recv_type\n增删 handler Config --> Created : set_send_type(-1) / set_recv_type(-1)\nclear_handlers Created --> Idle : port_delete() Config --> Idle : port_delete() Idle --> Created : 复用 ID @enduml ``` --- ## 8. 路由场景 ### 场景 1:传感器只发送(sensor → UART + TCP) ```c datarouter_port_t p = datarouter_port_create(); datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor); datarouter_port_add_handler(p, uart_send); datarouter_port_add_handler(p, tcp_send); datarouter_send_sensor(p, "temp:25.3", 9); // → uart_send(p, "temp:25.3", 9) // → tcp_send(p, "temp:25.3", 9) ``` ### 场景 2:RTCM 只接收 ```c datarouter_port_t p = datarouter_port_create(); datarouter_port_set_recv_type(p, DATAROUTER_RECV_rtcm); // 无 send_type,不注册 handler // 外设收到数据后由用户调回调: datarouter_on_recv_rtcm(p, data, len); ``` ### 场景 3:双向端口(status 发送 + command 接收) ```c datarouter_port_t p = datarouter_port_create(); datarouter_port_set_send_type(p, DATAROUTER_SEND_status); datarouter_port_set_recv_type(p, DATAROUTER_RECV_command); datarouter_port_add_handler(p, uart_send); // 发送 datarouter_send_status(p, "status:OK", 9); // 接收 datarouter_on_recv_command(p, "reboot", 6); ``` --- ## 9. 弱符号机制 ```plantuml @startuml package "libDataRouter.a" { component "弱符号\nvoid on_recv_rtcm(...){}" as Weak } package "用户代码" { component "强符号\nvoid on_recv_rtcm(...){...}" as Strong } package "最终链接产物" { component "使用用户版本" as Result } Strong --> Result Weak ..> Result : 后备 @enduml ``` --- ## 10. 错误码 | 返回值 | 含义 | |:------:|------| | 0 | 成功,所有 handler 被调用 | | -1 | 库未初始化(未调 init) | | -2 | 端口无效(越界/未创建/已删除) | | -3 | 端口 send_type 与调用的发送函数不匹配 | | -4 | 端口 handler 列表为空(count == 0) | --- ## 11. 配置扩展 ### 增加能力 ```c #define DATAROUTER_SEND_CAPABILITIES \ DATAROUTER_SEND(sensor, "Sensor data") \ DATAROUTER_SEND(debug, "Debug log") /* 新增发送能力 */ #define DATAROUTER_RECV_CAPABILITIES \ DATAROUTER_RECV(rtcm, "RTCM data") \ DATAROUTER_RECV(ota, "OTA firmware") /* 新增接收能力 */ ``` ### 自定义限制 ```bash cmake -DCMAKE_C_FLAGS="-DDATAROUTER_MAX_PORTS=128 -DDATAROUTER_MAX_HANDLERS_PER_PORT=8" ``` --- ## 12. 约束 | 约束 | 说明 | |------|------| | 能力声明 | 编译期固定,修改需重新编译 | | 最大端口数 | 默认 64,通过 `-D` 覆盖 | | 每端口 handler 上限 | 默认 4,通过 `-D` 覆盖 | | 线程安全 | 不支持(无锁),多线程需外部加锁 | | 弱符号 | GCC/Clang 原生支持 | | 内存分配 | 纯静态,无 malloc/free |