docs(libcomm): API 参考文档 + 进度更新 + 索引
- docs/public/libcomm/API-libcomm.md: 模块概述/数据结构/7个API详情/使用示例/依赖关系 - docs/README.md: 新增 libcomm 条目 + 阶段2依赖关系图 - COMPLETION.md: libcomm 标记完成 + 添加缺失测试清单
This commit is contained in:
parent
36cef7e23f
commit
16e3efb19c
|
|
@ -1,6 +1,6 @@
|
||||||
# RTU_ALL_AI 开发完成事项清单
|
# RTU_ALL_AI 开发完成事项清单
|
||||||
|
|
||||||
> 日期: 2026-07-07
|
> 日期: 2026-07-08
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -33,7 +33,8 @@
|
||||||
|
|
||||||
| 任务 | 模块 | 状态 |
|
| 任务 | 模块 | 状态 |
|
||||||
|------|------|:----:|
|
|------|------|:----:|
|
||||||
| 通讯抽象层 | `libcomm` | ⬜ |
|
| 通讯抽象层 | `libcomm` | ✅ |
|
||||||
|
| 通讯抽象层测试 | `test_comm.cpp`(17项全通过) | ✅ |
|
||||||
| Modbus 协议栈 | `libmodbus` | ⬜ |
|
| Modbus 协议栈 | `libmodbus` | ⬜ |
|
||||||
| IEC 60870-5-104 | `lib60870` | ⬜ |
|
| IEC 60870-5-104 | `lib60870` | ⬜ |
|
||||||
| IEC 点表解析 | `libiec` | ⬜ |
|
| IEC 点表解析 | `libiec` | ⬜ |
|
||||||
|
|
@ -49,6 +50,24 @@
|
||||||
| 端到端集成测试 | — | ⬜ |
|
| 端到端集成测试 | — | ⬜ |
|
||||||
| README 文档 | — | ⬜ |
|
| README 文档 | — | ⬜ |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 缺失测试的模块
|
||||||
|
|
||||||
|
| 模块 | 应写测试 | 优先级 |
|
||||||
|
|------|:------:|:------:|
|
||||||
|
| `liblist` | `test_list.c` | 低(头文件宏,无运行时逻辑) |
|
||||||
|
| `liblog` | `test_log.c` | 中 |
|
||||||
|
| `libfunc` | `test_func.c` | 中 |
|
||||||
|
| `libmd5` | `test_md5.c` | 低(算法标准,验证向量固定) |
|
||||||
|
| `libcJSON` | `test_cjson.c` | 中 |
|
||||||
|
| `libmy_xxhash` | `test_xxhash.c` | 低(算法标准) |
|
||||||
|
| `libtask` | `test_task.c` | 中 |
|
||||||
|
| `libxml` | `test_xml.c` | 低(thin wrapper over tinyxml2) |
|
||||||
|
| `libcmd` | `test_cmd.c` | 中 |
|
||||||
|
|
||||||
|
> 已有测试: `test_datacenter.cpp`(34项) ✅ `test_comm.cpp`(17项) ✅
|
||||||
|
|
||||||
## 阶段 4(预留)
|
## 阶段 4(预留)
|
||||||
|
|
||||||
ICP67 / IEC61850 MMS / MQTT / 嵌入式HTTP / PLC / 内部协议 —— 全部 ⬜
|
ICP67 / IEC61850 MMS / MQTT / 嵌入式HTTP / PLC / 内部协议 —— 全部 ⬜
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,9 @@
|
||||||
| libmy_xxhash | [API-libmy_xxhash.md](public/libmy_xxhash/API-libmy_xxhash.md) | 纯 C (开源库) | xxHash 快速哈希 |
|
| libmy_xxhash | [API-libmy_xxhash.md](public/libmy_xxhash/API-libmy_xxhash.md) | 纯 C (开源库) | xxHash 快速哈希 |
|
||||||
| libxml | [API-libxml.md](public/libxml/API-libxml.md) | C 接口+C++ 内部 | XML 解析(C接口包裹 tinyxml2) |
|
| libxml | [API-libxml.md](public/libxml/API-libxml.md) | C 接口+C++ 内部 | XML 解析(C接口包裹 tinyxml2) |
|
||||||
| libcmd | [API-libcmd.md](public/libcmd/API-libcmd.md) | C 接口+C++ 内部 | 命令注册/补全 + 内置 linenoise |
|
| libcmd | [API-libcmd.md](public/libcmd/API-libcmd.md) | C 接口+C++ 内部 | 命令注册/补全 + 内置 linenoise |
|
||||||
|
| libcomm | [API-libcomm.md](public/libcomm/API-libcomm.md) | C 接口+C++ 内部 | TCP/UDP/UART 通讯抽象层 |
|
||||||
|
|
||||||
### 模块依赖关系图
|
### 通讯与协议库 (protocol/ — 阶段 2 计划)
|
||||||
|
|
||||||
```
|
```
|
||||||
┌──────────┐
|
┌──────────┐
|
||||||
|
|
@ -61,6 +62,24 @@
|
||||||
│ │ 依赖: libxml + libcmd │ │
|
│ │ 依赖: libxml + libcmd │ │
|
||||||
│ │ + libmy_xxhash │ │
|
│ │ + libmy_xxhash │ │
|
||||||
└──────────┴─────────────────────────────┘
|
└──────────┴─────────────────────────────┘
|
||||||
|
|
||||||
|
┌──────────┐
|
||||||
|
│ myBase.h │
|
||||||
|
└────┬─────┘
|
||||||
|
│
|
||||||
|
▼
|
||||||
|
┌──────────────────┐
|
||||||
|
│ libcomm │ (通讯抽象层)
|
||||||
|
│ TCP/UDP/UART │ 阶段 2 首个模块
|
||||||
|
│ epoll 异步事件 │
|
||||||
|
└────┬───┬────┬────┘
|
||||||
|
│ │ │
|
||||||
|
┌──────────┼───┘ └──────────┐
|
||||||
|
▼ ▼ ▼
|
||||||
|
┌──────────┐ ┌──────────┐ ┌────────────┐
|
||||||
|
│libmodbus │ │lib60870 │ ... │libweb_server│ (协议栈)
|
||||||
|
│ (Modbus) │ │(IEC104) │ │ (Web 管理) │
|
||||||
|
└──────────┘ └──────────┘ └────────────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
### 构建与编译
|
### 构建与编译
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,366 @@
|
||||||
|
# API-libcomm — 通讯抽象层模块
|
||||||
|
|
||||||
|
> 版本: v1.0
|
||||||
|
> 日期: 2026-07-08
|
||||||
|
> 状态: 已实现(TCP/UDP 完整, UART 待实现)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 模块概述
|
||||||
|
|
||||||
|
libcomm 是 RTU 通讯装置的**通讯抽象层**,为上层协议栈(Modbus、IEC104 等)提供统一的 TCP/UDP/UART 通讯接口。
|
||||||
|
|
||||||
|
### 设计思想
|
||||||
|
|
||||||
|
- **类型统一**:同一套 API 操作 TCP 服务器/客户端、UDP、UART
|
||||||
|
- **异步事件驱动**:基于 epoll 单线程事件循环,非阻塞 I/O
|
||||||
|
- **回调解耦**:接收数据和状态变化通过回调通知上层
|
||||||
|
- **纯 C 接口**:`extern "C"` 包裹,C/C++ 均可调用
|
||||||
|
|
||||||
|
### 架构
|
||||||
|
|
||||||
|
```
|
||||||
|
┌──────────────────────────────────────────────┐
|
||||||
|
│ 协议层(libmodbus / lib60870) │
|
||||||
|
│ 调用 comm_create / comm_send / recv_cb │
|
||||||
|
├──────────────────────────────────────────────┤
|
||||||
|
│ libcomm(纯 C 接口层) │
|
||||||
|
│ ┌──────────┬──────────┬──────────────────┐ │
|
||||||
|
│ │ TCP 服务 │ TCP 客户 │ UDP 服务 / 客户 │ │
|
||||||
|
│ │ 器端 │ 端 │ │ │
|
||||||
|
│ └──────────┴──────────┴──────────────────┘ │
|
||||||
|
│ ┌──────────────────────────────────────────┐ │
|
||||||
|
│ │ epoll 事件循环 + fd 管理 + 状态机 │ │
|
||||||
|
│ └──────────────────────────────────────────┘ │
|
||||||
|
├──────────────────────────────────────────────┤
|
||||||
|
│ 实现层(C++: map/mutex + POSIX socket) │
|
||||||
|
└──────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
### 源文件结构
|
||||||
|
|
||||||
|
```
|
||||||
|
libcomm/
|
||||||
|
├── inc/
|
||||||
|
│ └── myComm.h # 对外 C 接口头文件
|
||||||
|
└── src/
|
||||||
|
├── comm_internal.h # 内部共享类型/全局变量/函数声明
|
||||||
|
├── comm_core.cpp # 核心: create/destroy/run/stop + epoll 事件循环
|
||||||
|
├── comm_tcp.cpp # TCP 服务器/客户端
|
||||||
|
├── comm_udp.cpp # UDP 通讯
|
||||||
|
└── comm_uart.cpp # UART 串口通讯
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 数据结构
|
||||||
|
|
||||||
|
### 2.1 通讯类型
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
COMM_TYPE_TCP_SERVER = 0, /** TCP 服务器(监听+accept) */
|
||||||
|
COMM_TYPE_TCP_CLIENT, /** TCP 客户端 */
|
||||||
|
COMM_TYPE_UDP_SERVER, /** UDP 服务器 */
|
||||||
|
COMM_TYPE_UDP_CLIENT, /** UDP 客户端 */
|
||||||
|
COMM_TYPE_UART /** UART 串口 */
|
||||||
|
} enum_comm_type;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.2 通讯状态
|
||||||
|
|
||||||
|
```c
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
COMM_STATE_DISCONNECTED = 0, /** 未连接 */
|
||||||
|
COMM_STATE_CONNECTING, /** 连接中 */
|
||||||
|
COMM_STATE_CONNECTED, /** 已连接 */
|
||||||
|
COMM_STATE_ERROR /** 错误状态 */
|
||||||
|
} enum_comm_state;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.3 参数结构体
|
||||||
|
|
||||||
|
```c
|
||||||
|
/** TCP 参数 */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char local_ip[64]; /** 本地 IP(服务器用) */
|
||||||
|
int local_port; /** 本地端口(服务器用) */
|
||||||
|
char remote_ip[64]; /** 远端 IP(客户端用) */
|
||||||
|
int remote_port; /** 远端端口(客户端用) */
|
||||||
|
} stru_tcp_para;
|
||||||
|
|
||||||
|
/** UDP 参数 */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char local_ip[64]; /** 本地 IP */
|
||||||
|
int local_port; /** 本地端口 */
|
||||||
|
char remote_ip[64]; /** 远端 IP(客户端用) */
|
||||||
|
int remote_port; /** 远端端口(客户端用) */
|
||||||
|
} stru_udp_para;
|
||||||
|
|
||||||
|
/** UART 参数 */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char device[128]; /** 串口设备路径(如 /dev/ttyS0) */
|
||||||
|
int baudrate; /** 波特率 */
|
||||||
|
int data_bits; /** 数据位(5/6/7/8) */
|
||||||
|
int stop_bits; /** 停止位(1/2) */
|
||||||
|
char parity; /** 校验位('N'/'E'/'O') */
|
||||||
|
} stru_uart_para;
|
||||||
|
|
||||||
|
/** 通讯参数联合体 */
|
||||||
|
typedef union
|
||||||
|
{
|
||||||
|
stru_tcp_para tcp;
|
||||||
|
stru_udp_para udp;
|
||||||
|
stru_uart_para uart;
|
||||||
|
} union_comm_para;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.4 回调函数类型
|
||||||
|
|
||||||
|
```c
|
||||||
|
/** 接收数据回调 */
|
||||||
|
typedef void (*comm_recv_cb)(int id, int fd, const unsigned char *data, int len);
|
||||||
|
|
||||||
|
/** 状态变化回调 */
|
||||||
|
typedef void (*comm_state_cb)(int id, int fd, int state);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.5 错误码
|
||||||
|
|
||||||
|
| 常量 | 值 | 说明 |
|
||||||
|
|------|-----|------|
|
||||||
|
| `COMM_OK` | 0 | 成功 |
|
||||||
|
| `COMM_ERR_PARAM` | -1 | 参数错误 |
|
||||||
|
| `COMM_ERR_MEM` | -2 | 内存不足 |
|
||||||
|
| `COMM_ERR_SOCKET` | -3 | Socket 创建失败 |
|
||||||
|
| `COMM_ERR_BIND` | -4 | 绑定失败 |
|
||||||
|
| `COMM_ERR_LISTEN` | -5 | 监听失败 |
|
||||||
|
| `COMM_ERR_CONNECT` | -6 | 连接失败 |
|
||||||
|
| `COMM_ERR_SEND` | -7 | 发送失败 |
|
||||||
|
| `COMM_ERR_NOT_FOUND` | -8 | 实例不存在 |
|
||||||
|
| `COMM_ERR_STATE` | -9 | 状态错误 |
|
||||||
|
| `COMM_ERR_INTERNAL` | -10 | 内部错误 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 接口函数
|
||||||
|
|
||||||
|
### 3.1 comm_create — 创建通讯实例
|
||||||
|
|
||||||
|
```c
|
||||||
|
int comm_create(int type, int debug, const union_comm_para *para);
|
||||||
|
```
|
||||||
|
|
||||||
|
**参数**:
|
||||||
|
- `type`:通讯类型(enum_comm_type)
|
||||||
|
- `debug`:是否打印调试信息(1=打印, 0=静默)
|
||||||
|
- `para`:通讯参数(根据 type 选择对应成员)
|
||||||
|
|
||||||
|
**返回值**:`>=0` 实例 ID,`<0` 错误码
|
||||||
|
|
||||||
|
**使用场景**:协议栈初始化时创建对应的通讯通道
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.2 comm_connect — 建立连接
|
||||||
|
|
||||||
|
```c
|
||||||
|
int comm_connect(int id);
|
||||||
|
```
|
||||||
|
|
||||||
|
**行为**(按类型):
|
||||||
|
- TCP 服务器:bind + listen,注册到 epoll
|
||||||
|
- TCP 客户端:非阻塞 connect,监听 EPOLLOUT 等待完成
|
||||||
|
- UDP:bind 本地端口
|
||||||
|
- UART:open 串口设备 + 配置波特率/数据位/停止位/校验
|
||||||
|
|
||||||
|
**返回值**:`COMM_OK` 成功,`<0` 错误码
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.3 comm_disconnect — 断开连接
|
||||||
|
|
||||||
|
```c
|
||||||
|
int comm_disconnect(int id);
|
||||||
|
```
|
||||||
|
|
||||||
|
关闭所有 fd(监听 + 客户端 + 本地),保留参数可重新 connect。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.4 comm_send — 发送数据
|
||||||
|
|
||||||
|
```c
|
||||||
|
int comm_send(int id, int fd, const unsigned char *data, int len);
|
||||||
|
```
|
||||||
|
|
||||||
|
**参数**:
|
||||||
|
- `fd`:目标 fd(TCP 服务器需指定客户端 fd)
|
||||||
|
- `data`/`len`:数据与长度
|
||||||
|
|
||||||
|
**返回值**:`>=0` 实际发送字节数,`<0` 错误码
|
||||||
|
|
||||||
|
**注意**:UDP 客户端会自动 sendto 到创建时指定的远端地址
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.5 comm_recv_register — 注册接收回调
|
||||||
|
|
||||||
|
```c
|
||||||
|
int comm_recv_register(int id, comm_recv_cb cb);
|
||||||
|
```
|
||||||
|
|
||||||
|
epoll 检测到可读后,自动调用此回调,传入 `(id, fd, data, len)`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.6 comm_state_register — 注册状态回调
|
||||||
|
|
||||||
|
```c
|
||||||
|
int comm_state_register(int id, comm_state_cb cb);
|
||||||
|
```
|
||||||
|
|
||||||
|
连接建立/断开/错误时回调,传入 `(id, fd, state)`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.7 comm_destroy — 销毁实例
|
||||||
|
|
||||||
|
```c
|
||||||
|
int comm_destroy(int id);
|
||||||
|
```
|
||||||
|
|
||||||
|
关闭所有 fd、释放内存。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3.8 comm_run / comm_stop — 事件循环
|
||||||
|
|
||||||
|
```c
|
||||||
|
int comm_run(void); /** 阻塞运行 epoll 事件循环 */
|
||||||
|
void comm_stop(void); /** 停止事件循环 */
|
||||||
|
```
|
||||||
|
|
||||||
|
**约定**:调用者在独立线程中调用 `comm_run()`。停止时调用 `comm_stop()`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 使用示例
|
||||||
|
|
||||||
|
### 4.1 TCP 客户端
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "myComm.h"
|
||||||
|
|
||||||
|
static void on_recv(int id, int fd, const unsigned char *data, int len)
|
||||||
|
{
|
||||||
|
printf("recv %d bytes on fd=%d\n", len, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void on_state(int id, int fd, int state)
|
||||||
|
{
|
||||||
|
if (state == COMM_STATE_CONNECTED)
|
||||||
|
{
|
||||||
|
printf("connected!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tcp_client_example(void)
|
||||||
|
{
|
||||||
|
union_comm_para para;
|
||||||
|
|
||||||
|
strcpy(para.tcp.remote_ip, "192.168.1.100");
|
||||||
|
para.tcp.remote_port = 502;
|
||||||
|
para.tcp.local_ip[0] = '\0';
|
||||||
|
para.tcp.local_port = 0;
|
||||||
|
|
||||||
|
int id = comm_create(COMM_TYPE_TCP_CLIENT, 1, ¶);
|
||||||
|
|
||||||
|
comm_recv_register(id, on_recv);
|
||||||
|
comm_state_register(id, on_state);
|
||||||
|
comm_connect(id);
|
||||||
|
|
||||||
|
/* 在另一个线程启动事件循环 */
|
||||||
|
comm_run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 TCP 服务器
|
||||||
|
|
||||||
|
```c
|
||||||
|
void tcp_server_example(void)
|
||||||
|
{
|
||||||
|
union_comm_para para;
|
||||||
|
|
||||||
|
strcpy(para.tcp.local_ip, "0.0.0.0");
|
||||||
|
para.tcp.local_port = 502;
|
||||||
|
|
||||||
|
int id = comm_create(COMM_TYPE_TCP_SERVER, 1, ¶);
|
||||||
|
|
||||||
|
comm_recv_register(id, on_recv);
|
||||||
|
comm_state_register(id, on_state);
|
||||||
|
comm_connect(id);
|
||||||
|
|
||||||
|
comm_run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 UDP
|
||||||
|
|
||||||
|
```c
|
||||||
|
void udp_example(void)
|
||||||
|
{
|
||||||
|
union_comm_para para;
|
||||||
|
|
||||||
|
strcpy(para.udp.local_ip, "0.0.0.0");
|
||||||
|
para.udp.local_port = 2404;
|
||||||
|
|
||||||
|
int id = comm_create(COMM_TYPE_UDP_SERVER, 1, ¶);
|
||||||
|
|
||||||
|
comm_recv_register(id, on_recv);
|
||||||
|
comm_connect(id);
|
||||||
|
comm_run();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 依赖关系
|
||||||
|
|
||||||
|
```
|
||||||
|
myBase.h → libcomm
|
||||||
|
(无其他模块依赖)
|
||||||
|
```
|
||||||
|
|
||||||
|
libcomm 是阶段 2 的第一个模块,被后续 `libmodbus`、`lib60870` 等协议栈依赖。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 程序运行流程
|
||||||
|
|
||||||
|
```
|
||||||
|
comm_create(type, para)
|
||||||
|
→ 分配 stru_comm_instance,拷贝参数,返回 id
|
||||||
|
→ 首次调用时初始化 epoll + eventfd
|
||||||
|
|
||||||
|
comm_connect(id)
|
||||||
|
→ TCP_SERVER: socket → bind → listen → epoll_add(listen_fd)
|
||||||
|
→ TCP_CLIENT: socket → nonblock-connect → epoll_add(fd, EPOLLOUT)
|
||||||
|
→ UDP: socket → bind → epoll_add(fd)
|
||||||
|
→ UART: open(device) → tcsetattr → epoll_add(fd)
|
||||||
|
|
||||||
|
comm_run() [阻塞,需在独立线程中调用]
|
||||||
|
→ epoll_wait 循环
|
||||||
|
→ EPOLLIN (listen_fd) → accept → epoll_add(client_fd) → state_cb
|
||||||
|
→ EPOLLIN (data_fd) → recv → recv_cb
|
||||||
|
→ EPOLLOUT → getsockopt(SO_ERROR) → connect 完成 → state_cb
|
||||||
|
→ EPOLLERR/HUP/RDHUP → close_fd → state_cb(DISCONNECTED)
|
||||||
|
|
||||||
|
comm_stop()
|
||||||
|
→ write(eventfd) → epoll 收到 → g_running = false → 退出循环
|
||||||
|
```
|
||||||
Loading…
Reference in New Issue