feat: 拆分发送和接收功能声明,优化config配置方式
This commit is contained in:
@@ -2,31 +2,37 @@
|
||||
|
||||
## 1. 设计目标
|
||||
|
||||
轻量级 C 语言数据路由库。核心思想:
|
||||
轻量级 C 语言数据路由库。发送与接收能力分开声明,每个端口独立设置发送类型和接收类型,支持多外设一对多广播路由。
|
||||
|
||||
- **报文类型(Channel)**:编译期通过宏声明的数据类型(如 `sensor` / `status` / `control`)
|
||||
- **端口(Port)**:运行期创建的连接点,绑定一个报文类型 + 一个物理外设发送 handler
|
||||
- **路由(Routing)**:将逻辑报文类型连接到实际的物理外设发送函数
|
||||
### 核心设计
|
||||
|
||||
```
|
||||
应用层 send_sensor(port, data)
|
||||
│
|
||||
▼
|
||||
库校验端口
|
||||
│
|
||||
▼
|
||||
调用注册的 handler(data) ← 用户实现:UART / TCP / CAN / 文件发送
|
||||
│
|
||||
▼
|
||||
物理外设
|
||||
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` 中声明,库自动生成代码 |
|
||||
| 运行期绑定外设 | 端口创建后,用户注册具体的发送 handler(函数指针) |
|
||||
| 收发分离 | 发送能力和接收能力在配置中分开声明,按需组合 |
|
||||
| 编译期确定能力 | 所有能力在 `datarouter_config.h` 中声明,库自动生成代码 |
|
||||
| 运行期绑定外设 | 端口创建后,通过 `add_handler` 注册物理外设发送函数 |
|
||||
| 一对多广播 | 一个端口可注册多个 handler,发送时逐一调用 |
|
||||
| 不关心物理外设 | 库不依赖任何外设 API,只调用用户提供的 handler |
|
||||
| 零动态内存 | 纯静态数组,无 malloc/free |
|
||||
|
||||
@@ -41,22 +47,22 @@
|
||||
left to right direction
|
||||
|
||||
rectangle "用户代码" as User {
|
||||
component "应用逻辑\n调用 datarouter_send_<type>()" as App
|
||||
component "datarouter_config.h\n声明报文类型" as Cfg
|
||||
component "外设 handler\nUART / TCP / CAN / 文件" as Handlers
|
||||
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 + 代码生成" as Hdr
|
||||
component "datarouter.c\n端口表 + handler 调用" as Impl
|
||||
component "datarouter.h\n公共 API + X-macro 展开" as Hdr
|
||||
component "datarouter.c\n端口表 + handler 遍历" as Impl
|
||||
}
|
||||
|
||||
App --> Hdr
|
||||
Cfg --> Hdr
|
||||
Impl --> Cfg
|
||||
Handlers --> Impl : 注册为 send_handler
|
||||
Callbacks --> Impl : 实现 on_recv_<type>
|
||||
Handlers --> Impl : 注册 handler
|
||||
Callbacks --> Impl : 实现 on_recv_<id>
|
||||
|
||||
@enduml
|
||||
```
|
||||
@@ -65,77 +71,60 @@ Callbacks --> Impl : 实现 on_recv_<type>
|
||||
|
||||
| 文件 | 职责 |
|
||||
|------|------|
|
||||
| `datarouter_config.h` | 用户在此声明所有报文类型 |
|
||||
| `datarouter.h` | 公共 API + X-macro 展开(enum + 发送函数声明 + 回调声明) |
|
||||
| `datarouter.c` | 发送函数实现 + handler 调用 + 端口管理 |
|
||||
| `example.c` | 使用示例 |
|
||||
| `tests/test_datarouter.c` | 31 个单元测试 |
|
||||
| `datarouter_config.h` | 分别声明 `SEND_CAPABILITIES` 和 `RECV_CAPABILITIES` |
|
||||
| `datarouter.h` | 公共 API + X-macro 展开(两组枚举 + 声明) |
|
||||
| `datarouter.c` | 端口表 + handler 列表遍历 + 弱符号回调 |
|
||||
| `example.c` | 收发分离示例 |
|
||||
| `tests/test_datarouter.c` | 27 个单元测试 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 核心概念
|
||||
## 3. 收发分离设计
|
||||
|
||||
### 3.1 报文类型(Channel)
|
||||
### 3.1 配置声明
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
object "DATAROUTER_CHANNEL(sensor, \"Sensor data\")" as C1
|
||||
object "DATAROUTER_CHANNEL(status, \"Status report\")" as C2
|
||||
object "DATAROUTER_CHANNEL(control, \"Control command\")" as C3
|
||||
```c
|
||||
// 发送能力 —— 只生成发送触发函数
|
||||
#define DATAROUTER_SEND_CAPABILITIES \
|
||||
DATAROUTER_SEND(sensor, "Sensor data report") \
|
||||
DATAROUTER_SEND(status, "Device status report")
|
||||
|
||||
note right of C1
|
||||
编译期展开产物:
|
||||
· DATAROUTER_CHANNEL_sensor = 0
|
||||
· int datarouter_send_sensor(port, data, len)
|
||||
· void datarouter_on_recv_sensor(port, data, len)
|
||||
· channel_names[0] = "sensor"
|
||||
· channel_descs[0] = "Sensor data"
|
||||
end note
|
||||
|
||||
C1 --> C2
|
||||
C2 --> C3
|
||||
@enduml
|
||||
// 接收能力 —— 只生成接收回调声明
|
||||
#define DATAROUTER_RECV_CAPABILITIES \
|
||||
DATAROUTER_RECV(rtcm, "RTCM correction data") \
|
||||
DATAROUTER_RECV(command, "Remote control command")
|
||||
```
|
||||
|
||||
### 3.2 端口与 handler
|
||||
### 3.2 展开产物
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
skinparam objectBorderColor black
|
||||
```
|
||||
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"}
|
||||
|
||||
object "端口 A" as PA {
|
||||
type = sensor
|
||||
handler = uart_send
|
||||
}
|
||||
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"}
|
||||
```
|
||||
|
||||
object "端口 B" as PB {
|
||||
type = sensor
|
||||
handler = tcp_send
|
||||
}
|
||||
### 3.3 端口组合示例
|
||||
|
||||
object "端口 C" as PC {
|
||||
type = status
|
||||
handler = uart_send
|
||||
}
|
||||
|
||||
object "UART发送函数" as UART
|
||||
object "TCP发送函数" as TCP
|
||||
|
||||
PA --> UART : 注册
|
||||
PB --> TCP : 注册
|
||||
PC --> UART : 注册
|
||||
|
||||
note right of PA
|
||||
同一报文类型 sensor
|
||||
可路由到不同外设
|
||||
end note
|
||||
|
||||
note right of PC
|
||||
不同报文类型 status
|
||||
可复用同一外设 UART
|
||||
end note
|
||||
|
||||
@enduml
|
||||
```
|
||||
端口 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 → 无功能
|
||||
```
|
||||
|
||||
---
|
||||
@@ -146,57 +135,42 @@ end note
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
== datarouter.h:4 次展开 ==
|
||||
|
||||
== datarouter.h: 3 次展开 ==
|
||||
-> datarouter_config.h: 获得两组宏列表
|
||||
|
||||
-> datarouter_config.h: #include 获得 DATAROUTER_CHANNELS
|
||||
datarouter.h -> "第 1 遍":
|
||||
#define DATAROUTER_SEND(id,desc) DATAROUTER_SEND_##id,
|
||||
DATAROUTER_SEND_CAPABILITIES → 发送 enum
|
||||
|
||||
datarouter.h -> "第 1 遍": #define DATAROUTER_CHANNEL(id,desc) DATAROUTER_CHANNEL_##id,
|
||||
note right: 生成 enum 通道枚举
|
||||
datarouter.h -> "第 2 遍":
|
||||
#define DATAROUTER_RECV(id,desc) DATAROUTER_RECV_##id,
|
||||
DATAROUTER_RECV_CAPABILITIES → 接收 enum
|
||||
|
||||
datarouter.h -> "第 2 遍": #define DATAROUTER_CHANNEL(id,desc) int datarouter_send_##id(...);
|
||||
note right: 生成发送触发函数声明
|
||||
datarouter.h -> "第 3 遍":
|
||||
#define DATAROUTER_SEND(id,desc) int datarouter_send_##id(...);
|
||||
DATAROUTER_SEND_CAPABILITIES → 发送函数声明
|
||||
|
||||
datarouter.h -> "第 3 遍": #define DATAROUTER_CHANNEL(id,desc) void datarouter_on_recv_##id(...);
|
||||
note right: 生成接收回调声明
|
||||
datarouter.h -> "第 4 遍":
|
||||
#define DATAROUTER_RECV(id,desc) void datarouter_on_recv_##id(...);
|
||||
DATAROUTER_RECV_CAPABILITIES → 接收回调声明
|
||||
|
||||
== datarouter.c: 3 次展开 ==
|
||||
== datarouter.c:4 次展开 ==
|
||||
|
||||
datarouter.c -> "第 4 遍": #define DATAROUTER_CHANNEL(id,desc) DATAROUTER_WEAK void ...
|
||||
note right: 弱符号回调默认空实现
|
||||
datarouter.c -> "第 5 遍":
|
||||
弱符号回调默认实现(DATAROUTER_RECV 展开)
|
||||
|
||||
datarouter.c -> "第 5 遍": #define DATAROUTER_CHANNEL(id,desc) int datarouter_send_##id(…) {…}
|
||||
note right: 发送函数实现 → 调用handler
|
||||
datarouter.c -> "第 6 遍":
|
||||
发送函数实现 body(DATAROUTER_SEND 展开)
|
||||
校验 → 遍历 handler 列表
|
||||
|
||||
datarouter.c -> "第 6 遍": #define DATAROUTER_CHANNEL(id,desc) #id, → channel_names[]
|
||||
datarouter.c -> "第 7 遍": #define DATAROUTER_CHANNEL(id,desc) desc, → channel_descs[]
|
||||
datarouter.c -> "第 7 ~ 8 遍":
|
||||
send_names[] / send_descs[]
|
||||
recv_names[] / recv_descs[]
|
||||
|
||||
@enduml
|
||||
```
|
||||
|
||||
### 4.2 展开示例(3 个通道)
|
||||
|
||||
```
|
||||
用户配置:
|
||||
DATAROUTER_CHANNEL(sensor, "Sensor data")
|
||||
DATAROUTER_CHANNEL(status, "Status report")
|
||||
DATAROUTER_CHANNEL(control, "Control command")
|
||||
|
||||
展开产物:
|
||||
enum: sensor = 0, status = 1, control = 2, CHANNEL_COUNT = 3
|
||||
|
||||
发送: int datarouter_send_sensor(uint32_t, const void*, size_t);
|
||||
int datarouter_send_status(…);
|
||||
int datarouter_send_control(…);
|
||||
|
||||
回调: void datarouter_on_recv_sensor(uint32_t, const void*, size_t);
|
||||
void datarouter_on_recv_status(…);
|
||||
void datarouter_on_recv_control(…);
|
||||
|
||||
元数据: names[] = {"sensor", "status", "control"}
|
||||
descs[] = {"Sensor data", "Status report", "Control command"}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 数据结构
|
||||
@@ -207,64 +181,68 @@ datarouter.c -> "第 7 遍": #define DATAROUTER_CHANNEL(id,desc) desc, → chann
|
||||
@startuml
|
||||
skinparam classAttributeIconSize 0
|
||||
|
||||
class "datarouter_channel (enum)" as Chan {
|
||||
+ DATAROUTER_CHANNEL_sensor = 0
|
||||
+ DATAROUTER_CHANNEL_status = 1
|
||||
+ DATAROUTER_CHANNEL_control = 2
|
||||
+ DATAROUTER_CHANNEL_COUNT = 3
|
||||
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 Table {
|
||||
- port_entry_t ports[64]
|
||||
- uint8_t initialized
|
||||
}
|
||||
|
||||
class "port_entry_t" as Entry {
|
||||
- int type
|
||||
- datarouter_send_handler_t handler
|
||||
- uint8_t in_use
|
||||
}
|
||||
|
||||
class "发送函数" as Send {
|
||||
+ int send_sensor(port, data, len)
|
||||
+ int send_status(port, data, len)
|
||||
+ int send_control(port, data, len)
|
||||
}
|
||||
|
||||
class "接收回调" as Recv {
|
||||
+ void on_recv_sensor(port, data, len) ← 用户实现
|
||||
+ void on_recv_status(port, data, len)
|
||||
+ void on_recv_control(port, data, len)
|
||||
+ void on_recv_rtcm(port, data, len) ← 用户实现
|
||||
+ void on_recv_command(port, data, len)
|
||||
}
|
||||
|
||||
Entry --> Chan : type ∈ enum
|
||||
Entry --> Handler : handler 函数指针
|
||||
Table --> Entry : ports[]
|
||||
Send --> Table : 校验端口 + 调用 handler
|
||||
Recv --> Send : 被用户从外设收数据时调用
|
||||
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 type; // 报文类型(DATAROUTER_CHANNEL_xxx / -1)
|
||||
datarouter_send_handler_t handler; // 外设发送函数(NULL 表示未注册)
|
||||
uint8_t in_use; // 1=已分配,0=空闲
|
||||
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 // 可由 -D 覆盖
|
||||
static port_entry_t ports[64]; // 静态数组,无动态内存
|
||||
static uint8_t initialized; // init/reset 标志
|
||||
#define DATAROUTER_MAX_PORTS 64
|
||||
static port_entry_t ports[DATAROUTER_MAX_PORTS];
|
||||
static uint8_t initialized;
|
||||
```
|
||||
|
||||
---
|
||||
@@ -274,54 +252,57 @@ static uint8_t initialized; // init/reset 标志
|
||||
### 6.1 初始化
|
||||
|
||||
```c
|
||||
void datarouter_init(void); // 幂等初始化
|
||||
void datarouter_reset(void); // 重置所有状态(测试隔离/热重启)
|
||||
void datarouter_init(void); // 幂等初始化
|
||||
void datarouter_reset(void); // 重置全部状态
|
||||
```
|
||||
|
||||
### 6.2 端口管理
|
||||
|
||||
```c
|
||||
datarouter_port_t datarouter_port_create(void); // 返回端口 ID 或 -1
|
||||
void datarouter_port_delete(port); // 删除端口,ID 可复用
|
||||
void datarouter_port_set_type(port, channel_id); // 指定报文类型
|
||||
int datarouter_port_get_type(port); // 获取报文类型,-1 表示无
|
||||
void datarouter_port_set_handler(port, handler); // 注册外设发送 handler
|
||||
datarouter_send_handler_t datarouter_port_get_handler(port); // 获取 handler
|
||||
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 发送触发函数(每通道 1 个,X-macro 生成)
|
||||
### 6.3 发送触发函数(每个 SEND 能力生成一个)
|
||||
|
||||
```c
|
||||
int datarouter_send_sensor(uint32_t port_id, const void *data, size_t len);
|
||||
int datarouter_send_status(uint32_t port_id, const void *data, size_t len);
|
||||
int datarouter_send_control(uint32_t port_id, const void *data, size_t len);
|
||||
int datarouter_send_sensor(port, data, len);
|
||||
int datarouter_send_status(port, data, len);
|
||||
```
|
||||
|
||||
返回值:
|
||||
| 值 | 含义 |
|
||||
|:--:|------|
|
||||
| 0 | 成功,handler 已被调用 |
|
||||
| -1 | 库未初始化 |
|
||||
| -2 | 端口无效或已删除 |
|
||||
| -3 | 端口类型与触发的报文类型不匹配 |
|
||||
| -4 | 端口未注册外设发送 handler |
|
||||
返回值:0 成功 / -1 未初始化 / -2 端口无效 / -3 send_type 不匹配 / -4 无 handler
|
||||
|
||||
### 6.4 接收回调声明(每通道 1 个,用户实现)
|
||||
### 6.4 接收回调(每个 RECV 能力生成一个声明)
|
||||
|
||||
```c
|
||||
void datarouter_on_recv_sensor(uint32_t port_id, const void *data, size_t len);
|
||||
void datarouter_on_recv_status(uint32_t port_id, const void *data, size_t len);
|
||||
void datarouter_on_recv_control(uint32_t port_id, const void *data, size_t len);
|
||||
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 元数据查询
|
||||
### 6.5 能力元数据(两组独立)
|
||||
|
||||
```c
|
||||
int datarouter_channel_count(void);
|
||||
const char *datarouter_channel_name(int channel_id);
|
||||
const char *datarouter_channel_desc(int channel_id);
|
||||
// 发送能力
|
||||
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);
|
||||
```
|
||||
|
||||
---
|
||||
@@ -335,36 +316,31 @@ const char *datarouter_channel_desc(int channel_id);
|
||||
actor "应用" as App
|
||||
participant "datarouter_send_sensor()" as Send
|
||||
participant "端口表" as Table
|
||||
participant "handler" as Handler
|
||||
participant "handlers[]" as HList
|
||||
participant "外设" as Dev
|
||||
|
||||
App -> Send : send_sensor(port=2, data, len)
|
||||
|
||||
group 校验
|
||||
Send -> Send : initialized?
|
||||
alt 未初始化
|
||||
Send --> App : return -1
|
||||
alt 否 → return -1
|
||||
end
|
||||
|
||||
Send -> Table : ports[2].in_use?
|
||||
alt 端口无效
|
||||
Send --> App : return -2
|
||||
alt 否 → return -2
|
||||
end
|
||||
|
||||
Send -> Table : ports[2].type == sensor?
|
||||
alt 类型不匹配
|
||||
Send --> App : return -3
|
||||
Send -> Table : ports[2].send_type == SENSOR?
|
||||
alt 否 → return -3
|
||||
end
|
||||
|
||||
Send -> Table : ports[2].handler != NULL?
|
||||
alt 无 handler
|
||||
Send --> App : return -4
|
||||
Send -> Table : ports[2].count > 0?
|
||||
alt 否 → return -4
|
||||
end
|
||||
end
|
||||
|
||||
Send -> Handler : handler(2, data, len)
|
||||
Handler -> Dev : UART_SendData(data, len)
|
||||
Handler --> Send : void
|
||||
loop for each handler in ports[2].handlers[]
|
||||
Send -> HList : handlers[i](port, data, len)
|
||||
HList -> Dev : 实际外设写入
|
||||
end
|
||||
|
||||
Send --> App : return 0
|
||||
@enduml
|
||||
```
|
||||
@@ -375,13 +351,10 @@ Send --> App : return 0
|
||||
@startuml
|
||||
actor "外设" as Dev
|
||||
participant "用户分发代码" as Dispatch
|
||||
participant "datarouter_on_recv_sensor()" as Callback
|
||||
participant "用户处理逻辑" as Process
|
||||
participant "on_recv_rtcm()" as Callback
|
||||
|
||||
Dev -> Dispatch : 收到数据,识别为 sensor 类型
|
||||
Dispatch -> Callback : on_recv_sensor(port_id, data, len)
|
||||
Callback -> Process : 解析数据、更新状态等
|
||||
Process --> Callback : void
|
||||
Dev -> Dispatch : 收到数据,识别为 rtcm 类型
|
||||
Dispatch -> Callback : on_recv_rtcm(port_id, data, len)
|
||||
Callback --> Dispatch : void
|
||||
@enduml
|
||||
```
|
||||
@@ -390,53 +363,66 @@ Callback --> Dispatch : void
|
||||
|
||||
```plantuml
|
||||
@startuml
|
||||
state "空闲\nin_use=0" as Idle
|
||||
state "已创建\nin_use=1\ntype=-1\nhandler=NULL" as Created
|
||||
state "已配置\nin_use=1\ntype=sensor\nhandler=..." as Config
|
||||
state "空闲" as Idle
|
||||
state "已创建\nsend=-1 recv=-1" as Created
|
||||
state "已配置" as Config
|
||||
|
||||
[*] --> Idle : datarouter_reset()
|
||||
[*] --> Idle : reset / 启动
|
||||
|
||||
Idle --> Created : datarouter_port_create()
|
||||
Idle --> Created : port_create()
|
||||
|
||||
Created --> Config : set_type + set_handler
|
||||
Config --> Config : set_type / set_handler\n可任意切换
|
||||
Config --> Created : set_type(-1) / set_handler(NULL)\n清除能力
|
||||
Created --> Config : set_send_type / set_recv_type / add_handler
|
||||
|
||||
Created --> Idle : datarouter_port_delete()
|
||||
Config --> Idle : datarouter_port_delete()
|
||||
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. 路由示例
|
||||
## 8. 路由场景
|
||||
|
||||
### 场景:传感器数据同时路由到 UART 和 TCP
|
||||
### 场景 1:传感器只发送(sensor → UART + TCP)
|
||||
|
||||
```
|
||||
应用
|
||||
│
|
||||
├─ send_sensor(sensor_uart_port, data, len)
|
||||
│ │
|
||||
│ ▼
|
||||
│ handler = uart_send → UART 外设
|
||||
│
|
||||
└─ send_sensor(sensor_tcp_port, data, len)
|
||||
│
|
||||
▼
|
||||
handler = tcp_send → 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);
|
||||
```
|
||||
端口 sensor_tcp 原 handler = tcp_send
|
||||
|
||||
datarouter_port_set_handler(sensor_tcp, file_send);
|
||||
### 场景 3:双向端口(status 发送 + command 接收)
|
||||
|
||||
端口 sensor_tcp 现 handler = file_send → 改为写入文件
|
||||
```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);
|
||||
```
|
||||
|
||||
---
|
||||
@@ -446,10 +432,10 @@ datarouter_port_set_handler(sensor_tcp, file_send);
|
||||
```plantuml
|
||||
@startuml
|
||||
package "libDataRouter.a" {
|
||||
component "弱符号\nvoid on_recv_sensor(...){}" as Weak
|
||||
component "弱符号\nvoid on_recv_rtcm(...){}" as Weak
|
||||
}
|
||||
package "用户代码" {
|
||||
component "强符号\nvoid on_recv_sensor(...){...}" as Strong
|
||||
component "强符号\nvoid on_recv_rtcm(...){...}" as Strong
|
||||
}
|
||||
package "最终链接产物" {
|
||||
component "使用用户版本" as Result
|
||||
@@ -459,44 +445,38 @@ Weak ..> Result : 后备
|
||||
@enduml
|
||||
```
|
||||
|
||||
- 库为每个回调提供 `__attribute__((weak))` 空实现
|
||||
- 用户定义同名函数自动覆盖
|
||||
- 未定义的回调在调用时静默空转
|
||||
|
||||
---
|
||||
|
||||
## 10. 错误码体系
|
||||
## 10. 错误码
|
||||
|
||||
| 返回值 | 含义 |
|
||||
|:------:|------|
|
||||
| 0 | 成功 |
|
||||
| -1 | 库未初始化 |
|
||||
| 0 | 成功,所有 handler 被调用 |
|
||||
| -1 | 库未初始化(未调 init) |
|
||||
| -2 | 端口无效(越界/未创建/已删除) |
|
||||
| -3 | 端口类型不匹配 |
|
||||
| -4 | 端口未注册发送 handler |
|
||||
| -3 | 端口 send_type 与调用的发送函数不匹配 |
|
||||
| -4 | 端口 handler 列表为空(count == 0) |
|
||||
|
||||
---
|
||||
|
||||
## 11. 配置扩展
|
||||
|
||||
### 增加报文类型
|
||||
|
||||
编辑 `datarouter_config.h`:
|
||||
### 增加能力
|
||||
|
||||
```c
|
||||
#define DATAROUTER_CHANNELS \
|
||||
DATAROUTER_CHANNEL(sensor, "Sensor data") \
|
||||
DATAROUTER_CHANNEL(status, "Status report") \
|
||||
DATAROUTER_CHANNEL(control, "Control command") \
|
||||
DATAROUTER_CHANNEL(debug, "Debug message") /* 新增 */
|
||||
#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" ...
|
||||
cmake -DCMAKE_C_FLAGS="-DDATAROUTER_MAX_PORTS=128 -DDATAROUTER_MAX_HANDLERS_PER_PORT=8"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -505,8 +485,9 @@ cmake -DCMAKE_C_FLAGS="-DDATAROUTER_MAX_PORTS=128" ...
|
||||
|
||||
| 约束 | 说明 |
|
||||
|------|------|
|
||||
| 报文类型 | 编译期固定,修改需重新编译 |
|
||||
| 最大端口数 | 默认 64,可由 `-D` 覆盖 |
|
||||
| 能力声明 | 编译期固定,修改需重新编译 |
|
||||
| 最大端口数 | 默认 64,通过 `-D` 覆盖 |
|
||||
| 每端口 handler 上限 | 默认 4,通过 `-D` 覆盖 |
|
||||
| 线程安全 | 不支持(无锁),多线程需外部加锁 |
|
||||
| 弱符号 | GCC/Clang 原生支持 |
|
||||
| 内存分配 | 纯静态,无 malloc/free |
|
||||
|
||||
Reference in New Issue
Block a user