7iwind 29c49057b4
Release / release (push) Successful in 19s
Merge pull request 'develop' (#12) from develop into main
Reviewed-on: #12
2026-07-26 13:30:36 +08:00
2026-07-26 01:46:47 +08:00
2026-07-25 23:08:48 +08:00
2026-07-25 23:08:48 +08:00

DataRouter

轻量级 C 语言数据路由库。发送能力和接收能力分开声明,端口独立设置 send_type 和 recv_type,支持多外设一对多广播路由。

概念

术语 说明
发送能力 (Send Capability) 编译期声明的可发送报文类型,生成 datarouter_send_<id>()
接收能力 (Recv Capability) 编译期声明的可接收报文类型,生成 datarouter_on_recv_<id>()
端口 (Port) 运行期连接点,独立设置 send_type + recv_type + handler 列表
Handler 用户实现的物理外设发送函数,一个端口可注册多个(默认上限 4)

快速开始

1. 声明能力

创建自己的 datarouter_config.h(可参考 datarouter_config_template.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")

库默认自带一份示例配置。将你的 datarouter_config.h 放到项目目录, 编译时添加 -I /path/to/your/config 即可覆盖。无需修改库源代码。

注意:确保你的配置目录在包含路径中出现在库目录之前,否则编译 datarouter.c 时仍会使用库的默认配置。在 CMake 中可参考:

# 你的 CMakeLists.txt
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})  # 全局优先
add_subdirectory(path/to/DataRouter)
target_link_libraries(my_app DataRouter)

2. 实现外设发送 handler

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. 创建端口

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. 实现接收回调

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 一览

初始化

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(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 能力生成一个)

int datarouter_send_sensor(port, data, len);   // 0 成功 / -1 未初始化
int datarouter_send_status(port, data, len);   // -2 端口无效
                                               // -3 send_type 不匹配
                                               // -4 无 handler

接收回调(每个 RECV 能力生成一个声明)

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);

库提供弱符号默认空实现,用户定义同名函数覆盖。

能力元数据(两组独立)

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

编译

cmake -S . -B build
cmake --build build

可选配置:

cmake -DCMAKE_C_FLAGS="-DDATAROUTER_MAX_PORTS=128 -DDATAROUTER_MAX_HANDLERS_PER_PORT=8"

测试

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
  • 无第三方库依赖
S
Description
No description provided
Readme MIT
282 KiB
2026-07-30 10:53:04 +08:00
Languages
C 74.5%
CMake 25.5%