diff --git a/.idea/misc.xml b/.idea/misc.xml
index 0b76fe5..e479d63 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -4,4 +4,5 @@
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 31dd62d..9edaf0b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,22 @@
-cmake_minimum_required(VERSION 4.3)
+cmake_minimum_required(VERSION 3.10)
project(DataRouter C)
set(CMAKE_C_STANDARD 11)
-add_library(DataRouter STATIC library.c)
+add_library(DataRouter STATIC datarouter.c)
+
+# 将库源码目录暴露给使用者,使其可通过 #include
+# 从自身 include path 覆盖默认配置。如果使用者未提供,则回退到库自带版本。
+target_include_directories(DataRouter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
+
+if(BUILD_EXAMPLES OR NOT DEFINED BUILD_EXAMPLES)
+ add_executable(example example.c)
+ target_link_libraries(example DataRouter)
+endif()
+
+if(BUILD_TESTING OR NOT DEFINED BUILD_TESTING)
+ enable_testing()
+ add_executable(test_datarouter tests/test_datarouter.c)
+ target_link_libraries(test_datarouter DataRouter)
+ add_test(NAME datarouter COMMAND test_datarouter)
+endif()
diff --git a/DESIGN.md b/DESIGN.md
new file mode 100644
index 0000000..0a411b9
--- /dev/null
+++ b/DESIGN.md
@@ -0,0 +1,493 @@
+# 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 |
diff --git a/README.md b/README.md
index 20e8180..882d3fb 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,204 @@
# 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
+- 无第三方库依赖
diff --git a/TEST_CASES.md b/TEST_CASES.md
new file mode 100644
index 0000000..28b2b9b
--- /dev/null
+++ b/TEST_CASES.md
@@ -0,0 +1,106 @@
+# DataRouter 单元测试用例文档
+
+## 测试环境
+
+| 项目 | 内容 |
+|------|------|
+| 语言标准 | C11 |
+| 编译器 | GCC 11.4.0 |
+| 测试框架 | 自定义轻量框架(宏 + goto cleanup) |
+| 构建系统 | CMake ≥ 3.10 |
+| 发送能力 | `sensor` / `status` |
+| 接收能力 | `rtcm` / `command` |
+
+## 运行方式
+
+```bash
+cmake -S . -B build
+cmake --build build
+ctest --test-dir build
+# 或直接运行:
+./build/test_datarouter
+```
+
+## 测试用例列表
+
+### 1. 未初始化(1 个)
+
+| # | 测试名 | 描述 | 步骤 | 预期 |
+|---|--------|------|------|------|
+| 1 | `error_uninit` | 未 init 时发送 | 不调 init 直接 `send_sensor(0, ...)` | 返回 -1 |
+
+### 2. 端口管理(4 个)
+
+| # | 测试名 | 描述 | 步骤 | 预期 |
+|---|--------|------|------|------|
+| 2 | `port_create_basic` | 基本创建 | `port_create()` | 返回 ≥ 0 |
+| 3 | `port_create_max` | 满容量(64) | 循环创建到满再尝试 | 64 个成功,第 65 个 INVALID |
+| 4 | `port_delete_invalid` | 删除无效 ID | `delete(-1)` + `delete(999)` | 不崩溃 |
+| 5 | `port_default_state` | 默认状态 | 创建端口,查 send/recv/handler | send_type=-1, recv_type=-1, count=0 |
+
+### 3. send_type / recv_type 独立设置(6 个)
+
+| # | 测试名 | 描述 | 步骤 | 预期 |
+|---|--------|------|------|------|
+| 6 | `send_type_set_get` | 设置发送类型 | `set_send_type(sensor)` → `get_send_type()` | 返回 sensor |
+| 7 | `recv_type_set_get` | 设置接收类型 | `set_recv_type(rtcm)` → `get_recv_type()` | 返回 rtcm |
+| 8 | `types_independent` | 收发互不干扰 | 同时 `set_send_type(sensor)` + `set_recv_type(command)` | get_send=sensor, get_recv=command |
+| 9 | `send_type_clear` | 清除发送类型 | `set_send_type(sensor)` → `set_send_type(-1)` | `get_send_type()` == -1 |
+| 10 | `recv_type_clear` | 清除接收类型 | `set_recv_type(rtcm)` → `set_recv_type(-1)` | `get_recv_type()` == -1 |
+| 11 | `types_from_invalid` | 无效端口查类型 | `get_send_type(-1/999)` / `get_recv_type(-1/999)` | 均返回 -1 |
+
+### 4. handler 增删(2 个)
+
+| # | 测试名 | 描述 | 步骤 | 预期 |
+|---|--------|------|------|------|
+| 12 | `handler_add_remove` | 添加后移除 | ① add(a) add(b) count=2 ② remove(a) count=1 | count 正确 |
+| 13 | `handler_clear` | 清除全部 | add 后 clear | count == 0 |
+
+### 5. 发送触发(9 个)
+
+| # | 测试名 | 描述 | 步骤 | 预期 |
+|---|--------|------|------|------|
+| 14 | `send_one_handler` | 单 handler 发送 | send_type + add_handler → send_sensor | 返回 0;handler 被调用 1 次 |
+| 15 | `send_multi_handlers` | 三个 handler 广播 | 注册 3 个 handler 后 send | 返回 0;handler 被调用 3 次 |
+| 16 | `send_type_mismatch` | 发送类型不匹配 | set_send_type(sensor) 但调用 send_status | 返回 -3;handler 不被调用 |
+| 17 | `send_no_handler` | 未注册 handler | 只 set_send_type 不 add_handler | 返回 -4 |
+| 18 | `send_no_send_type` | 没有 send_type | 端口只有 recv_type,调 send_sensor | 返回 -3 |
+| 19 | `send_remove_handler` | 移除后少广播 | 注册 2 handler → send count=2 → remove 1 → send count=1 | 数量正确 |
+| 20 | `send_clear_handlers` | 清空后无法发送 | add → clear → send | 返回 -4 |
+| 21 | `send_zero_length` | 零长度数据 | send(port, "x", 0) | 返回 0;handler 被调用 |
+| 22 | `send_null_data` | NULL 数据 | send(port, NULL, 0) | 返回 0;handler 被调用 |
+
+### 6. 接收回调(1 个)
+
+| # | 测试名 | 描述 | 步骤 | 预期 |
+|---|--------|------|------|------|
+| 23 | `recv_callbacks` | 用户实现接收回调 | ① `on_recv_rtcm(0, ...)` ② `on_recv_command(1, ...)` | 各自触发,互不干扰 |
+
+### 7. 能力元数据(2 个)
+
+| # | 测试名 | 描述 | 步骤 | 预期 |
+|---|--------|------|------|------|
+| 24 | `send_cap_meta` | 发送能力元数据 | 查 count / name / desc / 边界 | SEND 两组正确 |
+| 25 | `recv_cap_meta` | 接收能力元数据 | 查 count / name / desc / 边界 | RECV 两组正确 |
+
+### 8. 错误处理(2 个)
+
+| # | 测试名 | 描述 | 步骤 | 预期 |
+|---|--------|------|------|------|
+| 26 | `error_invalid_port` | 无效端口 | `send_sensor(999/-1, ...)` | 均返回 -2 |
+| 27 | `error_deleted_port` | 已删除端口 | 创建→设好→删除→send | 返回 -2 |
+
+## 覆盖矩阵
+
+| 功能模块 | 用例数 | 主要验证点 |
+|----------|:------:|------------|
+| 未初始化 | 1 | send → -1 |
+| 端口管理 | 4 | 创建/满容量/删除异常/默认状态 |
+| send_type / recv_type | 6 | 设置/清除/独立/无效端口 |
+| handler 增删 | 2 | 添加/移除/清空 |
+| 发送触发 | 9 | 单播/多播/类型不匹配/无handler/无send_type/移除后/清空后/零长/NULL |
+| 接收回调 | 1 | 用户实现覆盖弱符号 |
+| 能力元数据 | 2 | SEND 与 RECV 两组独立查询 |
+| 错误处理 | 2 | 无效端口/已删除端口 |
+
+**总计:27 个测试用例**
diff --git a/build/example b/build/example
new file mode 100755
index 0000000..9499c22
Binary files /dev/null and b/build/example differ
diff --git a/build/test_datarouter b/build/test_datarouter
new file mode 100755
index 0000000..edf203e
Binary files /dev/null and b/build/test_datarouter differ
diff --git a/datarouter.c b/datarouter.c
new file mode 100644
index 0000000..fd93586
--- /dev/null
+++ b/datarouter.c
@@ -0,0 +1,222 @@
+/**
+ * @file datarouter.c
+ * @brief 数据路由库 —— 实现
+ */
+
+#include "datarouter.h"
+#include
+
+#if defined(__GNUC__) || defined(__clang__)
+#define DATAROUTER_WEAK __attribute__((weak))
+#else
+#define DATAROUTER_WEAK
+#endif
+
+#ifndef DATAROUTER_MAX_PORTS
+#define DATAROUTER_MAX_PORTS 64
+#endif
+
+typedef struct {
+ int send_type;
+ int recv_type;
+ datarouter_send_handler_t handlers[DATAROUTER_MAX_HANDLERS_PER_PORT];
+ int count;
+ uint8_t in_use;
+} port_entry_t;
+
+static port_entry_t ports[DATAROUTER_MAX_PORTS];
+static uint8_t initialized;
+
+/* ---- 发送能力元数据 ---- */
+
+static const char *send_names[] = {
+#define DATAROUTER_SEND(id, desc) #id,
+ DATAROUTER_SEND_CAPABILITIES
+#undef DATAROUTER_SEND
+};
+
+static const char *send_descs[] = {
+#define DATAROUTER_SEND(id, desc) desc,
+ DATAROUTER_SEND_CAPABILITIES
+#undef DATAROUTER_SEND
+};
+
+/* ---- 接收能力元数据 ---- */
+
+static const char *recv_names[] = {
+#define DATAROUTER_RECV(id, desc) #id,
+ DATAROUTER_RECV_CAPABILITIES
+#undef DATAROUTER_RECV
+};
+
+static const char *recv_descs[] = {
+#define DATAROUTER_RECV(id, desc) desc,
+ DATAROUTER_RECV_CAPABILITIES
+#undef DATAROUTER_RECV
+};
+
+/* ---- 弱符号接收回调默认实现 ---- */
+
+#define DATAROUTER_RECV(id, desc) \
+ DATAROUTER_WEAK void datarouter_on_recv_##id( \
+ uint32_t port_id, const void *data, size_t len) \
+ { \
+ (void)port_id; (void)data; (void)len; \
+ }
+DATAROUTER_RECV_CAPABILITIES
+#undef DATAROUTER_RECV
+
+/* ---- 发送触发函数实现 ---- */
+
+#define DATAROUTER_SEND(id, desc) \
+ int datarouter_send_##id(uint32_t port_id, const void *data, size_t len) \
+ { \
+ if (!initialized) return -1; \
+ if (port_id >= DATAROUTER_MAX_PORTS || !ports[port_id].in_use) return -2; \
+ if (ports[port_id].send_type != DATAROUTER_SEND_##id) return -3; \
+ if (ports[port_id].count == 0) return -4; \
+ for (int _i = 0; _i < ports[port_id].count; _i++) \
+ ports[port_id].handlers[_i](port_id, data, len); \
+ return 0; \
+ }
+DATAROUTER_SEND_CAPABILITIES
+#undef DATAROUTER_SEND
+
+/* ---- 端口管理 ---- */
+
+void datarouter_init(void)
+{
+ if (initialized) return;
+ memset(ports, 0, sizeof(ports));
+ initialized = 1;
+}
+
+void datarouter_reset(void)
+{
+ initialized = 0;
+ memset(ports, 0, sizeof(ports));
+}
+
+datarouter_port_t datarouter_port_create(void)
+{
+ if (!initialized) return DATAROUTER_INVALID_PORT;
+ for (int i = 0; i < DATAROUTER_MAX_PORTS; i++) {
+ if (!ports[i].in_use) {
+ ports[i].in_use = 1;
+ ports[i].send_type = -1;
+ ports[i].recv_type = -1;
+ ports[i].count = 0;
+ return (datarouter_port_t)i;
+ }
+ }
+ return DATAROUTER_INVALID_PORT;
+}
+
+void datarouter_port_delete(datarouter_port_t port)
+{
+ if (!initialized) return;
+ if (port < 0 || port >= DATAROUTER_MAX_PORTS) return;
+ ports[port].in_use = 0;
+}
+
+void datarouter_port_set_send_type(datarouter_port_t port, int cap_id)
+{
+ if (!initialized) return;
+ if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return;
+ ports[port].send_type = cap_id;
+}
+
+int datarouter_port_get_send_type(datarouter_port_t port)
+{
+ if (!initialized) return -1;
+ if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return -1;
+ return ports[port].send_type;
+}
+
+void datarouter_port_set_recv_type(datarouter_port_t port, int cap_id)
+{
+ if (!initialized) return;
+ if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return;
+ ports[port].recv_type = cap_id;
+}
+
+int datarouter_port_get_recv_type(datarouter_port_t port)
+{
+ if (!initialized) return -1;
+ if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return -1;
+ return ports[port].recv_type;
+}
+
+int datarouter_port_add_handler(datarouter_port_t port, datarouter_send_handler_t handler)
+{
+ if (!initialized) return -1;
+ if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return -1;
+ if (ports[port].count >= DATAROUTER_MAX_HANDLERS_PER_PORT) return -2;
+ for (int i = 0; i < ports[port].count; i++)
+ if (ports[port].handlers[i] == handler) return -3;
+ ports[port].handlers[ports[port].count++] = handler;
+ return 0;
+}
+
+int datarouter_port_remove_handler(datarouter_port_t port, datarouter_send_handler_t handler)
+{
+ if (!initialized) return -1;
+ if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return -1;
+ for (int i = 0; i < ports[port].count; i++) {
+ if (ports[port].handlers[i] == handler) {
+ ports[port].handlers[i] = ports[port].handlers[--ports[port].count];
+ return 0;
+ }
+ }
+ return -2;
+}
+
+void datarouter_port_clear_handlers(datarouter_port_t port)
+{
+ if (!initialized) return;
+ if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return;
+ ports[port].count = 0;
+}
+
+int datarouter_port_handler_count(datarouter_port_t port)
+{
+ if (!initialized) return -1;
+ if (port < 0 || port >= DATAROUTER_MAX_PORTS || !ports[port].in_use) return -1;
+ return ports[port].count;
+}
+
+/* ---- 元数据查询 ---- */
+
+int datarouter_send_cap_count(void)
+{
+ return DATAROUTER_SEND_CAP_COUNT;
+}
+
+const char *datarouter_send_cap_name(int cap_id)
+{
+ if (cap_id < 0 || cap_id >= DATAROUTER_SEND_CAP_COUNT) return NULL;
+ return send_names[cap_id];
+}
+
+const char *datarouter_send_cap_desc(int cap_id)
+{
+ if (cap_id < 0 || cap_id >= DATAROUTER_SEND_CAP_COUNT) return NULL;
+ return send_descs[cap_id];
+}
+
+int datarouter_recv_cap_count(void)
+{
+ return DATAROUTER_RECV_CAP_COUNT;
+}
+
+const char *datarouter_recv_cap_name(int cap_id)
+{
+ if (cap_id < 0 || cap_id >= DATAROUTER_RECV_CAP_COUNT) return NULL;
+ return recv_names[cap_id];
+}
+
+const char *datarouter_recv_cap_desc(int cap_id)
+{
+ if (cap_id < 0 || cap_id >= DATAROUTER_RECV_CAP_COUNT) return NULL;
+ return recv_descs[cap_id];
+}
diff --git a/datarouter.h b/datarouter.h
new file mode 100644
index 0000000..26aa877
--- /dev/null
+++ b/datarouter.h
@@ -0,0 +1,126 @@
+/**
+ * @file datarouter.h
+ * @brief 数据路由库 —— 公共接口
+ *
+ * ## 概念
+ *
+ * - **发送能力 (Send Capability)**:编译期声明的可发送报文类型
+ * - **接收能力 (Recv Capability)**:编译期声明的可接收报文类型
+ * - **端口 (Port)**:运行期连接点,独立设置 send_type + recv_type + 外设 handler 列表
+ *
+ * ## 使用流程
+ *
+ * 1. 创建 datarouter_config.h 声明发送和接收能力(见 datarouter_config_template.h)
+ * 2. 编译时通过 -I 指向你的配置目录;若无,库使用内置默认配置
+ * 3. datarouter_init() 初始化
+ * 4. port_create() 创建端口
+ * 5. port_set_send_type() 设置发送类型 / port_set_recv_type() 设置接收类型
+ * 6. port_add_handler() 注册外设发送函数
+ * 7. 调 datarouter_send_() 触发发送(库调用所有 handler)
+ * 8. 实现 datarouter_on_recv_() 处理接收数据
+ */
+
+#ifndef DATAROUTER_H
+#define DATAROUTER_H
+
+#include
+#include
+
+/*
+ * 配置加载策略:
+ * 1. 优先从 include path 搜索 (用户提供的版本)
+ * 2. 找不到则回退到库自带的 "datarouter_config.h"(默认配置)
+ *
+ * 用户只需将自己的 datarouter_config.h 放到项目目录,
+ * 编译时添加 -I /path/to/your/config 即可覆盖内置配置。
+ */
+#if defined(__has_include)
+# if __has_include()
+# include
+# else
+# include "datarouter_config.h"
+# endif
+#else
+# include "datarouter_config.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ========== 发送能力枚举 ========== */
+
+enum datarouter_send_cap {
+#define DATAROUTER_SEND(id, desc) DATAROUTER_SEND_##id,
+ DATAROUTER_SEND_CAPABILITIES
+#undef DATAROUTER_SEND
+ DATAROUTER_SEND_CAP_COUNT
+};
+
+/* ========== 接收能力枚举 ========== */
+
+enum datarouter_recv_cap {
+#define DATAROUTER_RECV(id, desc) DATAROUTER_RECV_##id,
+ DATAROUTER_RECV_CAPABILITIES
+#undef DATAROUTER_RECV
+ DATAROUTER_RECV_CAP_COUNT
+};
+
+/* ========== 外设发送 handler 类型 ========== */
+
+typedef void (*datarouter_send_handler_t)(uint32_t port_id, const void *data, size_t len);
+
+#ifndef DATAROUTER_MAX_HANDLERS_PER_PORT
+#define DATAROUTER_MAX_HANDLERS_PER_PORT 4
+#endif
+
+/* ========== 发送触发函数(每个发送能力生成一个) ========== */
+
+#define DATAROUTER_SEND(id, desc) \
+ int datarouter_send_##id(uint32_t port_id, const void *data, size_t len);
+DATAROUTER_SEND_CAPABILITIES
+#undef DATAROUTER_SEND
+
+/* ========== 接收回调声明(每个接收能力生成一个,用户实现) ========== */
+
+#define DATAROUTER_RECV(id, desc) \
+ void datarouter_on_recv_##id(uint32_t port_id, const void *data, size_t len);
+DATAROUTER_RECV_CAPABILITIES
+#undef DATAROUTER_RECV
+
+/* ========== 端口管理 API ========== */
+
+typedef int32_t datarouter_port_t;
+#define DATAROUTER_INVALID_PORT ((datarouter_port_t)-1)
+
+void datarouter_init(void);
+void datarouter_reset(void);
+
+datarouter_port_t datarouter_port_create(void);
+void datarouter_port_delete(datarouter_port_t port);
+
+void datarouter_port_set_send_type(datarouter_port_t port, int cap_id);
+int datarouter_port_get_send_type(datarouter_port_t port);
+void datarouter_port_set_recv_type(datarouter_port_t port, int cap_id);
+int datarouter_port_get_recv_type(datarouter_port_t port);
+
+int datarouter_port_add_handler(datarouter_port_t port, datarouter_send_handler_t handler);
+int datarouter_port_remove_handler(datarouter_port_t port, datarouter_send_handler_t handler);
+void datarouter_port_clear_handlers(datarouter_port_t port);
+int datarouter_port_handler_count(datarouter_port_t port);
+
+/* ========== 能力元数据查询 ========== */
+
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DATAROUTER_H */
\ No newline at end of file
diff --git a/datarouter_config.h b/datarouter_config.h
new file mode 100644
index 0000000..8086134
--- /dev/null
+++ b/datarouter_config.h
@@ -0,0 +1,40 @@
+/**
+ * @file datarouter_config.h
+ * @brief 数据路由默认配置
+ *
+ * 这是库内置的默认配置,提供示例能力声明。
+ * 用户可自定义此文件以实现自己的报文类型:
+ *
+ * 1. 复制当前文件到你的项目目录
+ * 2. 按需修改 DATAROUTER_SEND_CAPABILITIES / DATAROUTER_RECV_CAPABILITIES
+ * 3. 编译时添加 -I /path/to/your/config 覆盖库的默认配置
+ *
+ * 覆盖后库将使用你的版本,无需修改库源代码。
+ */
+
+#ifndef DATAROUTER_CONFIG_H
+#define DATAROUTER_CONFIG_H
+
+/**
+ * @def DATAROUTER_SEND_CAPABILITIES
+ * @brief 发送能力列表
+ *
+ * 每行格式:DATAROUTER_SEND(标识符, "描述")
+ * 每项生成:发送触发函数 datarouter_send_(port, data, len)
+ */
+#define DATAROUTER_SEND_CAPABILITIES \
+ DATAROUTER_SEND(sensor, "Sensor data report") \
+ DATAROUTER_SEND(status, "Device status report")
+
+/**
+ * @def DATAROUTER_RECV_CAPABILITIES
+ * @brief 接收能力列表
+ *
+ * 每行格式:DATAROUTER_RECV(标识符, "描述")
+ * 每项生成:接收回调声明 datarouter_on_recv_(port, data, len)
+ */
+#define DATAROUTER_RECV_CAPABILITIES \
+ DATAROUTER_RECV(rtcm, "RTCM correction data") \
+ DATAROUTER_RECV(command, "Remote control command")
+
+#endif /* DATAROUTER_CONFIG_H */
\ No newline at end of file
diff --git a/datarouter_config_template.h b/datarouter_config_template.h
new file mode 100644
index 0000000..d102e4f
--- /dev/null
+++ b/datarouter_config_template.h
@@ -0,0 +1,51 @@
+/**
+ * @file datarouter_config_template.h
+ * @brief 数据路由配置模板 —— 复制此文件到项目目录并修改
+ *
+ * 使用方法:
+ * 1. 将此文件复制到你的项目目录,重命名为 datarouter_config.h
+ * 2. 修改下面的 DATAROUTER_SEND_CAPABILITIES 和 DATAROUTER_RECV_CAPABILITIES
+ * 3. 编译时添加 -I /path/to/your/project
+ * 4. 库将自动使用你的配置,无需修改库源代码
+ *
+ * 格式说明:
+ * 发送能力:DATAROUTER_SEND(标识符, "描述")
+ * 接收能力:DATAROUTER_RECV(标识符, "描述")
+ *
+ * 标识符只能包含字母、数字、下划线。
+ * 描述为字符串字面量。
+ *
+ * 示例配置:
+ * // 传感器设备:只需发送
+ * #define DATAROUTER_SEND_CAPABILITIES \
+ * DATAROUTER_SEND(sensor, "Sensor data report")
+ * #define DATAROUTER_RECV_CAPABILITIES
+ *
+ * // 遥控设备:只需接收
+ * #define DATAROUTER_SEND_CAPABILITIES
+ * #define DATAROUTER_RECV_CAPABILITIES \
+ * DATAROUTER_RECV(command, "Remote command")
+ *
+ * // 网关设备:同时收发
+ * #define DATAROUTER_SEND_CAPABILITIES \
+ * DATAROUTER_SEND(status, "Status report")
+ * #define DATAROUTER_RECV_CAPABILITIES \
+ * DATAROUTER_RECV(config, "Configuration update")
+ */
+
+#ifndef DATAROUTER_CONFIG_H
+#define DATAROUTER_CONFIG_H
+
+/* ========== 在此声明你的发送能力 ========== */
+
+#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")
+
+#endif /* DATAROUTER_CONFIG_H */
\ No newline at end of file
diff --git a/example.c b/example.c
new file mode 100644
index 0000000..2760478
--- /dev/null
+++ b/example.c
@@ -0,0 +1,93 @@
+/**
+ * @file example.c
+ * @brief 数据路由库使用示例
+ *
+ * 展示:
+ * - 发送能力和接收能力分开声明(sensor 只发送,rtcm 只接收)
+ * - 端口独立设置 send_type 和 recv_type
+ * - 一个端口可同时拥有发送和接收能力
+ */
+
+#include "datarouter.h"
+#include
+#include
+
+/* ---- 外设发送 handler ---- */
+
+static void uart_send(uint32_t port_id, const void *data, size_t len)
+{
+ printf("[UART] port %u: %.*s\n", port_id, (int)len, (const char *)data);
+}
+
+static void tcp_send(uint32_t port_id, const void *data, size_t len)
+{
+ printf("[TCP] port %u: %.*s\n", port_id, (int)len, (const char *)data);
+}
+
+/* ---- 接收回调实现 ---- */
+
+void datarouter_on_recv_rtcm(uint32_t port_id, const void *data, size_t len)
+{
+ printf("[RX:rtcm] port %u: %.*s\n", port_id, (int)len, (const char *)data);
+}
+
+void datarouter_on_recv_command(uint32_t port_id, const void *data, size_t len)
+{
+ printf("[RX:cmd] port %u: %.*s\n", port_id, (int)len, (const char *)data);
+}
+
+int main(void)
+{
+ datarouter_init();
+
+ /* 查询能力 */
+ printf("Send capabilities: %d\n", datarouter_send_cap_count());
+ for (int i = 0; i < datarouter_send_cap_count(); i++)
+ printf(" SEND [%d] %s - %s\n", i,
+ datarouter_send_cap_name(i), datarouter_send_cap_desc(i));
+
+ printf("Recv capabilities: %d\n", datarouter_recv_cap_count());
+ for (int i = 0; i < datarouter_recv_cap_count(); i++)
+ printf(" RECV [%d] %s - %s\n", i,
+ datarouter_recv_cap_name(i), datarouter_recv_cap_desc(i));
+
+ /*
+ * 端口 A:只有发送能力 —— 上报传感器数据
+ */
+ datarouter_port_t tx_port = datarouter_port_create();
+ datarouter_port_set_send_type(tx_port, DATAROUTER_SEND_sensor);
+ datarouter_port_add_handler(tx_port, uart_send);
+ datarouter_port_add_handler(tx_port, tcp_send);
+
+ printf("\n--- send sensor (UART + TCP) ---\n");
+ datarouter_send_sensor(tx_port, "temperature:25.3", 16);
+ /* 该端口没有 recv_type,不能接收任何报文 */
+
+ /*
+ * 端口 B:只有接收能力 —— 接收 RTCM 修正
+ */
+ datarouter_port_t rtcm_port = datarouter_port_create();
+ datarouter_port_set_recv_type(rtcm_port, DATAROUTER_RECV_rtcm);
+ /* 没有 send_type,也没有 handler —— 不能发送 */
+
+ printf("\n--- simulate receive RTCM ---\n");
+ datarouter_on_recv_rtcm(rtcm_port, "rtcm_data_v3.2", 14);
+
+ /*
+ * 端口 C:同时有收发能力 —— 接收命令 + 上报状态
+ */
+ datarouter_port_t bi_port = datarouter_port_create();
+ datarouter_port_set_send_type(bi_port, DATAROUTER_SEND_status);
+ datarouter_port_set_recv_type(bi_port, DATAROUTER_RECV_command);
+ datarouter_port_add_handler(bi_port, uart_send);
+
+ printf("\n--- bidirectional port ---\n");
+ datarouter_send_status(bi_port, "status:OK", 9);
+ datarouter_on_recv_command(bi_port, "reboot", 6);
+
+ /* 清理 */
+ datarouter_port_delete(tx_port);
+ datarouter_port_delete(rtcm_port);
+ datarouter_port_delete(bi_port);
+ return 0;
+}
diff --git a/library.c b/library.c
deleted file mode 100644
index f431745..0000000
--- a/library.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "library.h"
-
-#include
-
-void hello(void) {
- printf("Hello, World!\n");
-}
diff --git a/library.h b/library.h
deleted file mode 100644
index f16761c..0000000
--- a/library.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef DATAROUTER_LIBRARY_H
-#define DATAROUTER_LIBRARY_H
-
-void hello(void);
-
-#endif // DATAROUTER_LIBRARY_H
diff --git a/tests/test_datarouter.c b/tests/test_datarouter.c
new file mode 100644
index 0000000..8f895fa
--- /dev/null
+++ b/tests/test_datarouter.c
@@ -0,0 +1,389 @@
+/**
+ * @file test_datarouter.c
+ * @brief 数据路由库单元测试
+ *
+ * 覆盖:
+ * - 端口管理
+ * - send_type / recv_type 独立设置
+ * - 多 handler 增删
+ * - 发送调用(一对多广播)
+ * - 接收回调
+ * - 发送/接收能力元数据各自独立
+ * - 错误处理
+ */
+
+#include "datarouter.h"
+#include
+#include
+
+/* ================================================================
+ * 测试框架
+ * ================================================================ */
+
+static int _total_run, _total_pass, _total_fail;
+static int _err;
+static const char *_cur_name;
+
+#define FIXTURE_MAX 16
+typedef struct {
+ datarouter_port_t ports[FIXTURE_MAX];
+ int count;
+} fixture_t;
+
+#define FIXTURE_INIT(f) memset((f), 0, sizeof(*(f)))
+#define FIXTURE_PUSH(f, p) do { if ((f)->count < FIXTURE_MAX) (f)->ports[(f)->count++] = (p); } while (0)
+#define FIXTURE_CLEAN(f) do { for (int _i = 0; _i < (f)->count; _i++) datarouter_port_delete((f)->ports[_i]); } while (0)
+#define FIXTURE_CREATE(f) ({ datarouter_port_t _p = datarouter_port_create(); FIXTURE_PUSH(f, _p); _p; })
+
+#define TEST_START(name) \
+ static void test_##name(void) \
+ { \
+ fixture_t _fix; \
+ FIXTURE_INIT(&_fix); \
+ _cur_name = #name; \
+ _err = 0;
+
+#define TEST_END() \
+cleanup: \
+ FIXTURE_CLEAN(&_fix); \
+ if (_err) { _total_fail++; printf(" FAIL %s\n", _cur_name); } \
+ else { _total_pass++; printf(" PASS %s\n", _cur_name); } \
+ _total_run++; \
+ }
+
+#define CHECK(cond, ...) do { \
+ if (!(cond)) { \
+ printf(" %s [line %d]: ", _cur_name, __LINE__); \
+ printf(__VA_ARGS__); \
+ printf("\n"); \
+ _err = 1; \
+ goto cleanup; \
+ } \
+ } while (0)
+
+/* ================================================================
+ * 测试用 handler
+ * ================================================================ */
+
+static int _h_cnt;
+static void _h(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
+static void _h_a(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
+static void _h_b(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
+static void _h_c(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
+static void _h_d(uint32_t p, const void *d, size_t l) { (void)p; (void)d; (void)l; _h_cnt++; }
+static void reset_h(void) { _h_cnt = 0; }
+
+/* ================================================================
+ * 1. 未初始化
+ * ================================================================ */
+
+TEST_START(error_uninit)
+ CHECK(datarouter_send_sensor(0, "d", 1) == -1, "expected -1");
+TEST_END()
+
+/* ================================================================
+ * 2. 端口管理
+ * ================================================================ */
+
+TEST_START(port_create_basic)
+ CHECK(FIXTURE_CREATE(&_fix) >= 0, "create failed");
+TEST_END()
+
+TEST_START(port_create_max)
+ int c = 0;
+ for (int i = 0; i < 64; i++) {
+ datarouter_port_t p = datarouter_port_create();
+ if (p == DATAROUTER_INVALID_PORT) break;
+ FIXTURE_PUSH(&_fix, p); c++;
+ }
+ CHECK(c >= 64, "got %d", c);
+ CHECK(datarouter_port_create() == DATAROUTER_INVALID_PORT, NULL);
+TEST_END()
+
+TEST_START(port_delete_invalid)
+ datarouter_port_delete(-1); datarouter_port_delete(999);
+TEST_END()
+
+TEST_START(port_default_state)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ CHECK(datarouter_port_get_send_type(p) == -1, "send_type should be -1");
+ CHECK(datarouter_port_get_recv_type(p) == -1, "recv_type should be -1");
+ CHECK(datarouter_port_handler_count(p) == 0, "handler count 0");
+TEST_END()
+
+/* ================================================================
+ * 3. send_type / recv_type 独立设置
+ * ================================================================ */
+
+TEST_START(send_type_set_get)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ CHECK(datarouter_port_get_send_type(p) == DATAROUTER_SEND_sensor, NULL);
+TEST_END()
+
+TEST_START(recv_type_set_get)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_recv_type(p, DATAROUTER_RECV_rtcm);
+ CHECK(datarouter_port_get_recv_type(p) == DATAROUTER_RECV_rtcm, NULL);
+TEST_END()
+
+TEST_START(types_independent)
+ /* 一个端口同时设置 send_type 和 recv_type,互不干扰 */
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ datarouter_port_set_recv_type(p, DATAROUTER_RECV_command);
+ CHECK(datarouter_port_get_send_type(p) == DATAROUTER_SEND_sensor, NULL);
+ CHECK(datarouter_port_get_recv_type(p) == DATAROUTER_RECV_command, NULL);
+TEST_END()
+
+TEST_START(send_type_clear)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ datarouter_port_set_send_type(p, -1);
+ CHECK(datarouter_port_get_send_type(p) == -1, NULL);
+TEST_END()
+
+TEST_START(recv_type_clear)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_recv_type(p, DATAROUTER_RECV_rtcm);
+ datarouter_port_set_recv_type(p, -1);
+ CHECK(datarouter_port_get_recv_type(p) == -1, NULL);
+TEST_END()
+
+TEST_START(types_from_invalid)
+ CHECK(datarouter_port_get_send_type(-1) == -1, NULL);
+ CHECK(datarouter_port_get_recv_type(-1) == -1, NULL);
+ CHECK(datarouter_port_get_send_type(999) == -1, NULL);
+ CHECK(datarouter_port_get_recv_type(999) == -1, NULL);
+TEST_END()
+
+/* ================================================================
+ * 4. 多 handler
+ * ================================================================ */
+
+TEST_START(handler_add_remove)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ CHECK(datarouter_port_add_handler(p, _h_a) == 0, NULL);
+ CHECK(datarouter_port_add_handler(p, _h_b) == 0, NULL);
+ CHECK(datarouter_port_handler_count(p) == 2, NULL);
+ CHECK(datarouter_port_remove_handler(p, _h_a) == 0, NULL);
+ CHECK(datarouter_port_handler_count(p) == 1, NULL);
+TEST_END()
+
+TEST_START(handler_clear)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_add_handler(p, _h);
+ datarouter_port_clear_handlers(p);
+ CHECK(datarouter_port_handler_count(p) == 0, NULL);
+TEST_END()
+
+/* ================================================================
+ * 5. 发送触发
+ * ================================================================ */
+
+TEST_START(send_one_handler)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ datarouter_port_add_handler(p, _h);
+ reset_h();
+ CHECK(datarouter_send_sensor(p, "d", 1) == 0, NULL);
+ CHECK(_h_cnt == 1, "handler called %d times", _h_cnt);
+TEST_END()
+
+TEST_START(send_multi_handlers)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ datarouter_port_add_handler(p, _h_a);
+ datarouter_port_add_handler(p, _h_b);
+ datarouter_port_add_handler(p, _h_c);
+ reset_h();
+ CHECK(datarouter_send_sensor(p, "d", 1) == 0, NULL);
+ CHECK(_h_cnt == 3, "handler called %d times", _h_cnt);
+TEST_END()
+
+TEST_START(send_type_mismatch)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ datarouter_port_add_handler(p, _h);
+ reset_h();
+ CHECK(datarouter_send_status(p, "d", 1) == -3, "expected -3");
+ CHECK(_h_cnt == 0, NULL);
+TEST_END()
+
+TEST_START(send_no_handler)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ CHECK(datarouter_send_sensor(p, "d", 1) == -4, "expected -4");
+TEST_END()
+
+TEST_START(send_no_send_type)
+ /* 端口只有 recv_type,没有 send_type */
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_recv_type(p, DATAROUTER_RECV_rtcm);
+ CHECK(datarouter_send_sensor(p, "d", 1) == -3, "expected -3 (send_type unset)");
+TEST_END()
+
+TEST_START(send_remove_handler)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ datarouter_port_add_handler(p, _h_a);
+ datarouter_port_add_handler(p, _h_b);
+ reset_h(); datarouter_send_sensor(p, "d", 1); CHECK(_h_cnt == 2, NULL);
+ datarouter_port_remove_handler(p, _h_a);
+ reset_h(); datarouter_send_sensor(p, "d", 1); CHECK(_h_cnt == 1, NULL);
+TEST_END()
+
+TEST_START(send_clear_handlers)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ datarouter_port_add_handler(p, _h);
+ datarouter_port_clear_handlers(p);
+ CHECK(datarouter_send_sensor(p, "d", 1) == -4, "expected -4");
+TEST_END()
+
+TEST_START(send_zero_length)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ datarouter_port_add_handler(p, _h);
+ reset_h();
+ CHECK(datarouter_send_sensor(p, "x", 0) == 0, NULL);
+ CHECK(_h_cnt == 1, NULL);
+TEST_END()
+
+TEST_START(send_null_data)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ datarouter_port_add_handler(p, _h);
+ reset_h();
+ CHECK(datarouter_send_sensor(p, NULL, 0) == 0, NULL);
+ CHECK(_h_cnt == 1, NULL);
+TEST_END()
+
+/* ================================================================
+ * 6. 接收回调
+ * ================================================================ */
+
+static int _rx_r, _rx_c;
+void datarouter_on_recv_rtcm(uint32_t p, const void *d, size_t l)
+ { (void)p; (void)d; (void)l; _rx_r++; }
+void datarouter_on_recv_command(uint32_t p, const void *d, size_t l)
+ { (void)p; (void)d; (void)l; _rx_c++; }
+
+TEST_START(recv_callbacks)
+ _rx_r = _rx_c = 0;
+ datarouter_on_recv_rtcm(0, "d", 1);
+ CHECK(_rx_r == 1 && _rx_c == 0, "rtcm=%d cmd=%d", _rx_r, _rx_c);
+ datarouter_on_recv_command(1, "d", 1);
+ CHECK(_rx_r == 1 && _rx_c == 1, "rtcm=%d cmd=%d", _rx_r, _rx_c);
+TEST_END()
+
+/* ================================================================
+ * 7. 能力元数据(两组独立)
+ * ================================================================ */
+
+TEST_START(send_cap_meta)
+ CHECK(datarouter_send_cap_count() == 2, NULL);
+ CHECK(strcmp(datarouter_send_cap_name(0), "sensor") == 0, NULL);
+ CHECK(strcmp(datarouter_send_cap_desc(0), "Sensor data report") == 0, NULL);
+ CHECK(strcmp(datarouter_send_cap_name(1), "status") == 0, NULL);
+ CHECK(strcmp(datarouter_send_cap_desc(1), "Device status report") == 0, NULL);
+ CHECK(datarouter_send_cap_name(-1) == NULL, NULL);
+ CHECK(datarouter_send_cap_name(99) == NULL, NULL);
+TEST_END()
+
+TEST_START(recv_cap_meta)
+ CHECK(datarouter_recv_cap_count() == 2, NULL);
+ CHECK(strcmp(datarouter_recv_cap_name(0), "rtcm") == 0, NULL);
+ CHECK(strcmp(datarouter_recv_cap_desc(0), "RTCM correction data") == 0, NULL);
+ CHECK(strcmp(datarouter_recv_cap_name(1), "command") == 0, NULL);
+ CHECK(strcmp(datarouter_recv_cap_desc(1), "Remote control command") == 0, NULL);
+ CHECK(datarouter_recv_cap_name(-1) == NULL, NULL);
+ CHECK(datarouter_recv_cap_desc(99) == NULL, NULL);
+TEST_END()
+
+/* ================================================================
+ * 8. 错误
+ * ================================================================ */
+
+TEST_START(error_invalid_port)
+ CHECK(datarouter_send_sensor(999, "d", 1) == -2, NULL);
+ CHECK(datarouter_send_sensor(-1, "d", 1) == -2, NULL);
+TEST_END()
+
+TEST_START(error_deleted_port)
+ datarouter_port_t p = FIXTURE_CREATE(&_fix);
+ datarouter_port_set_send_type(p, DATAROUTER_SEND_sensor);
+ datarouter_port_add_handler(p, _h);
+ datarouter_port_delete(p);
+ CHECK(datarouter_send_sensor(p, "d", 1) == -2, NULL);
+ _fix.count--;
+TEST_END()
+
+/* ================================================================
+ * 主函数
+ * ================================================================ */
+
+#define RUN(name) do { reset_h(); test_##name(); } while (0)
+
+int main(void)
+{
+ printf("==== DataRouter Unit Tests ====\n\n");
+
+ printf("[uninitialized]\n");
+ RUN(error_uninit);
+
+ datarouter_init();
+
+ printf("\n[port management]\n");
+ RUN(port_create_basic);
+ RUN(port_create_max);
+ RUN(port_delete_invalid);
+ RUN(port_default_state);
+ printf("\n");
+
+ datarouter_reset(); datarouter_init();
+ printf("[send_type / recv_type]\n");
+ RUN(send_type_set_get);
+ RUN(recv_type_set_get);
+ RUN(types_independent);
+ RUN(send_type_clear);
+ RUN(recv_type_clear);
+ RUN(types_from_invalid);
+ printf("\n");
+
+ printf("[handler add/remove]\n");
+ RUN(handler_add_remove);
+ RUN(handler_clear);
+ printf("\n");
+
+ printf("[send trigger]\n");
+ RUN(send_one_handler);
+ RUN(send_multi_handlers);
+ RUN(send_type_mismatch);
+ RUN(send_no_handler);
+ RUN(send_no_send_type);
+ RUN(send_remove_handler);
+ RUN(send_clear_handlers);
+ RUN(send_zero_length);
+ RUN(send_null_data);
+ printf("\n");
+
+ printf("[receive callback]\n");
+ RUN(recv_callbacks);
+ printf("\n");
+
+ printf("[capability metadata]\n");
+ RUN(send_cap_meta);
+ RUN(recv_cap_meta);
+ printf("\n");
+
+ printf("[error handling]\n");
+ RUN(error_invalid_port);
+ RUN(error_deleted_port);
+ printf("\n");
+
+ printf("==============================\n");
+ printf(" total: %d | pass: %d | fail: %d\n\n",
+ _total_run, _total_pass, _total_fail);
+ return _total_fail > 0 ? 1 : 0;
+}