RTU_ALL_AI/docs/protocol/libicp67/API-libicp67.md

10 KiB
Raw Permalink Blame History

libicp67 — ICP67 自定义协议库 API 参考

模块概述

位置: src/protocol/libicp67/

定位: ICP67 二进制协议引擎 — 负责帧定界、编解码、重传管理。纯 C 实现extern "C" 接口。

依赖: liblog (日志), POSIX sem_t (信号量)

被依赖: libself_ptl (自协议应用层)

协议帧格式

| 0x67 | len(2B) | 0x67 | src | dst | dir | ti | cot | info_addr(2B) | dev_addr(4B) | data... | CRC(1B) | 0x16 |
| 帧头1 |  长度   | 帧头2 |  源 | 目的 | 方向 |类型| 原因 |   信息体地址    |   设备地址    |  数据体  |   校验和  |  帧尾  |
  • 帧头: 0x67 0x67 (双字节定界)
  • 校验: 8-bit 累加和 (CRC8)
  • 帧尾: 0x16
  • 设备地址: src/dst 取值 0=维护软件, 1=主板, 2=主板, 3=采样板, 4=LCD

架构

libself_ptl (应用层)
    │
    ├─ icp67_init() 初始化
    ├─ icp67_set_*_cb() 注册 17 个回调
    │
    ▼
libicp67 (协议引擎)
    ├─ icp67_search_frame() 帧定界
    ├─ icp67_decode() 解码分发
    ├─ icp67_timer_handler() 重传管理
    ├─ Sender 函数 (13个) 组帧发送
    └─ 16 种 TI 解码函数

文件清单

文件 行数 说明
release/inc/myIcp67.h 331 公共契约: 帧结构、回调类型、stru_icp67、常量宏
src/protocol/libicp67/inc/icp67.h ~500 内部头: TI/COT枚举、ASDU结构体、内部API声明
src/protocol/libicp67/src/icp67_frame.c 126 帧定界、CRC校验、帧构造、调试打印
src/protocol/libicp67/src/icp67_decode.c 1024 16种TI解码+文件/ZIP子命令分发
src/protocol/libicp67/src/icp67_core.c 645 初始化、回调注册、重传管理、Sender函数、定时器

对外 API

初始化

void icp67_init(stru_icp67 *p_icp67, icp67_send_cb send_cb, void *arg);

初始化协议实例,绑定发送回调和用户参数。内部自动绑定:

  • search_frame_cbicp67_search_frame()
  • decode_cbicp67_decode()
  • timer_handler_cbicp67_timer_handler()
  • 创建重传信号量 rtx_sem
  • 初始化 13 个 Sender 回调为内部函数
  • 设置超时参数 tm_out = 1000ms / 10ms = 100 tick
int icp67_set_ao_cfg_md5(stru_icp67 *p_icp67, uint8_t *p_md5);

设置 AO 参数配置的 MD5 校验值 (16字节),用于后续 TI_1/TI_2 帧的 MD5 验证。

回调注册 (17 个 setter)

pop_out 类 (3 个) — 解码后回调注册:

函数 注册回调 触发场景
icp67_set_ao_pop_out_cb ao_pop_out_cb TI_1 参数读取响应
icp67_set_iec_point_tbl_pop_out_cb iec_point_tbl_pop_out_cb TI_3 点表读取响应
icp67_set_self_check_pop_out_cb self_check_pop_out_cb TI_6 自检响应

文件操作类 (6 个):

函数 注册回调 触发场景
icp67_set_dir_pop_out_cb dir_pop_out_cb TI_11_2 目录响应
icp67_set_file_read_act_confirm_cb file_read_act_confirm_cb TI_11_4 读文件激活响应
icp67_set_file_read_cb file_read_cb TI_11_5 读文件内容
icp67_set_file_write_act_confirm_cb file_write_act_confirm_cb TI_11_8 写文件激活响应
icp67_set_file_write_confirm_cb file_write_confirm_cb TI_11_10 写文件确认
icp67_set_file_write_end_cb file_write_end_cb TI_11_10 写文件结束

ZIP 类 (2 个):

函数 注册回调 触发场景
icp67_set_zip_dir_pop_out_cb zip_dir_pop_out_cb TI_30_1 录波目录
icp67_set_zip_file_pop_out_cb zip_file_pop_out_cb TI_30_3 录波文件内容

数据传输类 (6 个):

函数 注册回调 触发场景
icp67_set_mx_trans_cb mx_trans_cb TI_200 遥测传输
icp67_set_st_trans_cb st_trans_cb TI_201 遥信传输
icp67_set_dd_trans_cb dd_trans_cb TI_202 电度传输
icp67_set_soe_trans_cb soe_trans_cb TI_204 SOE 事件
icp67_set_fault_trans_cb fault_trans_cb TI_205 故障事件
icp67_set_mx_change_cb mx_change_cb TI_207 遥测扰动

帧操作 (内部 API)

int  icp67_search_frame(uint8_t *p_data, uint16_t len, uint16_t *p_pos, uint16_t *p_valid_len);
int  icp67_decode(stru_icp67 *p_icp67, uint8_t *p_data, uint16_t len);
void icp67_timer_handler(stru_icp67 *p_icp67);
void icp67_make_head(uint8_t dst, uint8_t ti, uint8_t cot, uint16_t inf, uint8_t *p_tx, uint16_t *tx_len);
void icp67_make_tail(uint8_t *p_tx, uint16_t *tx_len);
void icp67_show_frame(uint8_t *p_data, uint16_t len);

重传管理 (线程安全)

void icp67_rtx_flag_set(stru_icp67 *p_icp67, uint8_t flag, uint8_t resend_cnt, uint32_t tm_cnt);
void icp67_rtx_flag_get(stru_icp67 *p_icp67, uint8_t *flag, uint8_t *resend_cnt, uint32_t *tm_cnt);
void icp67_rtx_resend_inc(stru_icp67 *p_icp67);
void icp67_rtx_tm_inc(stru_icp67 *p_icp67);

所有读写操作通过 rtx_sem 信号量保护。

核心数据结构

stru_icp67 — 协议实例

typedef struct _icp67 {
    void                  *arg;              // 用户数据 (interface ID)
    icp67_send_cb          send_cb;          // 发送回调 (→物理层)
    icp67_search_frame_cb  search_frame_cb;  // 帧搜索
    icp67_decode_cb        decode_cb;        // 解码
    icp67_timer_handler_cb timer_handler_cb; // 定时器
    stru_genneral_method   method;           // 回调表 (实例化)
    uint8_t                md5[16];          // AO参数MD5
    uint8_t                tx[2048];         // 发送缓冲区
    uint8_t                resend_tx[2048];  // 重发备份
    uint8_t                rtx_flag;         // 重传标志
    sem_t                  rtx_sem;          // 重传信号量
    uint8_t                resend_cnt;       // 重发计数
    uint32_t               tm_out;           // 超时阈值
    uint32_t               tm_cnt;           // 当前tick
} icp67;

stru_genneral_method — 回调表 (29 个函数指针)

  • Sender 组 (13个): 方向 self_ptl → icp67 → 物理层

    • ao_get, ao_set, iec_point_tbl_get, time_set, self_check_get
    • upgrade_start, dir_read, file_read_act, file_write_act
    • file_write, file_read_confirm, file_write_end_confirm
  • Receiver 组 (16个): 方向 物理层 → icp67 → self_ptl

    • ao_pop_out, iec_point_tbl_pop_out, self_check_pop_out
    • dir_pop_out, file_read_act_confirm, file_read
    • file_write_act_confirm, file_write_confirm, file_write_end
    • zip_dir_pop_out, zip_file_pop_out
    • mx_trans, st_trans, dd_trans, soe_trans, fault_trans, mx_change

TI 消息类型清单

TI 名称 COT 方向 说明
1 读独立编码参数 5→7 请求→响应 带 MD5 校验的参数读取
2 写独立编码参数 6→7 激活→确认 参数写入,含 MD5
3 读组合编码参数 5→7 请求→响应 点表/校准数据,支持分帧
4 写组合编码参数 - - 空桩 (未使用)
5 对时 5→7 请求→响应 终端时间同步
6 自检读取 5→7 请求→响应 终端状态/版本号
9 升级 5→7 请求→响应 固件升级
11 文件操作 5→7 请求→响应 目录/文件读写, 9 种子命令
30 录波文件 5 上行 ZIP 波形目录/文件传输
200 遥测传输 6 上行 采样板→主板 MX
201 遥信传输 6 上行 采样板→主板 ST
202 计量传输 6 上行 采样板→主板 DD
203 遥控交互 - - 空桩 (未使用)
204 SOE 传输 3 上行 事件顺序记录
205 故障传输 3 上行 故障事件 (含 ST+MX)
207 扰动传输 3 上行 遥测扰动数据

与原工程的差异

维度 原 RTU (icp67.cpp) 重构后 (纯C 4文件)
回调表 全局 g_genneral_method 实例化 p_icp67->method
TI 映射 C++ std::map C 数组 + 线性查表
故障解码 std::vector 固定数组 [MAX_FAULT_*_INFO]
文件格式 icp67.cpp (1429行) + general_method.cpp (88行) 4 文件: frame(126) + decode(1024) + core(645) + header(~830)
语言 C++ 纯 C (extern "C" 接口)
常量 魔数 命名 #define (ICP67_TX_BUF_SIZE 等)
空桩 TI_4/TI_203 空 LOG_E + RX_FLAG 设置

完成状态

已完成

  • 帧定界/校验 (search_frame, CRC)
  • 16 种 TI 解码 (含文件/ZIP 子命令)
  • 13 个 Sender 函数 (组帧发送)
  • 17 个回调 setter (实例化注册)
  • 重传管理 (4 函数, sem 线程安全)
  • 定时器处理 (10ms tick, 5 次重试)
  • TI_4/TI_203 空桩填充
  • 多实例隔离 (回调表实例化)
  • 魔数 → 命名常量
  • C 数组查表替代 std::map
  • 单元测试 (21 项全通过)

未完成

  • TI_203 遥控交互实现 (FTU 固件不支持, 暂缓)

以下两项因 FTU 固件不可改动, 已删除: CRC 升级 (需 FTU 同步改帧格式) 帧序号/去重 (需 FTU 同步改帧格式)

新增功能 (2026-07-09)

可配置超时/重试

// 旧
void icp67_init(stru_icp67 *p, icp67_send_cb cb, void *arg);

// 新: 传 0 使用默认值 (1000ms, 5次)
void icp67_init(stru_icp67 *p, icp67_send_cb cb, void *arg,
                uint32_t tm_out_ms, uint8_t resend_max);

// 示例
icp67_init(&icp, send_cb, &iface, 2000, 3);  // 串口慢速: 2s超时, 重试3次
icp67_init(&icp, send_cb, &iface, 0, 0);     // 使用默认值

stru_icp67 新增字段: resend_max, tm_out_ms

零拷贝环形缓冲区搜索

int icp67_search_frame_in_ring(const uint8_t *buf, uint16_t size,
    uint16_t rptr, uint16_t cnt,
    uint16_t *p_pos, uint16_t *p_valid_len);

直接从环形缓冲区读指针扫描帧, 省去 get_rx_data() 的 2048 字节 memcpyself_ptl 已接入, 仅 IEC-104 检测保留一次全量拷贝。

测试覆盖

测试项 覆盖内容 状态
T1 帧构造 make_head + make_tail
T2 帧搜索 正常帧、无效帧头、NULL参数
T3 CRC 基本累加、溢出回绕
T4 初始化 绑定回调、信号量、超时参数
T5 重传管理 set/get、resend_inc
T6 回调注册 17 个 setter 全路径
T7 解码无效 NULL参数
T8 定时器 NULL、空闲态
T9 MD5 正常设置、NULL参数
T10 未知 TI 0xFF 帧
T11 Sender self_check_get、iec_point_tbl_get、NULL安全
T12 解码 TI TI_1 MD5 匹配、TI_4 空桩
T13 多实例 实例间回调隔离