From 2c10cbbe7c4a362a2d3421d404177a8a920af51c Mon Sep 17 00:00:00 2001 From: ypc <15051963820@163.com> Date: Tue, 16 Jun 2026 14:57:45 +0800 Subject: [PATCH] =?UTF-8?q?<=E4=BF=AE=E6=94=B9>=201=E3=80=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96icp67=E6=A8=A1=E5=9D=97=EF=BC=9B2=E3=80=81=E4=BC=98?= =?UTF-8?q?=E5=8C=96self=5Fptl=E5=BA=94=E7=94=A8=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mimo/plan/icp67多实例重构方案.md | 277 +++++++++ mimo/plan/iec101帧搜索方案.md | 31 + mimo/plan/self_ptl缺陷优化方案.md | 34 + mimo/工程/libicp67模块分析.md | 153 +++++ mimo/工程/libself_ptl模块分析.md | 232 +++++++ mimo/问题处理文档.md | 55 +- release/inc/myIcp67.h | 62 +- src/protocol/libicp67/inc/general_method.h | 8 - src/protocol/libicp67/inc/icp67.h | 13 +- src/protocol/libicp67/src/general_method.cpp | 553 +---------------- src/protocol/libicp67/src/icp67.cpp | 583 +++++++++++++++--- .../libcom_decode/src/decode_frame_codec.cpp | 2 +- src/system/libdatacenter/src/dc_signal.cpp | 1 + src/system/libself_ptl/inc/self_ptl.h | 3 +- src/system/libself_ptl/src/method.cpp | 78 +-- src/system/libself_ptl/src/self_ptl.cpp | 315 +++++++--- 16 files changed, 1596 insertions(+), 804 deletions(-) create mode 100644 mimo/plan/icp67多实例重构方案.md create mode 100644 mimo/plan/iec101帧搜索方案.md create mode 100644 mimo/plan/self_ptl缺陷优化方案.md create mode 100644 mimo/工程/libicp67模块分析.md create mode 100644 mimo/工程/libself_ptl模块分析.md delete mode 100644 src/protocol/libicp67/inc/general_method.h diff --git a/mimo/plan/icp67多实例重构方案.md b/mimo/plan/icp67多实例重构方案.md new file mode 100644 index 0000000..e30a4c3 --- /dev/null +++ b/mimo/plan/icp67多实例重构方案.md @@ -0,0 +1,277 @@ +# ICP67 模块多实例重构方案 + +## 概述 + +将 `libicp67` 从全局单例回调架构重构为多实例安全架构,同时修复重传竞态 bug、填充空桩、统一硬编码为命名常量。 + +--- + +## 涉及文件 + +| 文件 | 改动量 | +|------|--------| +| `release/inc/myIcp67.h` | 添加宏常量、添加 method 字段到 stru_icp67、修改 setter 声明 | +| `src/protocol/libicp67/src/icp67.cpp` | 移除 `icp67_get_genneral_method()` 调用、修复重传竞态、填充空桩 | +| `src/protocol/libicp67/src/general_method.cpp` | 删除 `g_genneral_method`、setter 改为实例化、method 初始化移入 icp67_init | +| `src/protocol/libicp67/inc/general_method.h` | 删除文件(不再需要) | +| `src/protocol/libicp67/inc/icp67.h` | 添加内部常量宏 | +| `src/system/libself_ptl/src/self_ptl.cpp` | setter 调用增加 p_icp67 参数、get 类回调改为直接通过 p_icp67->method 访问 | +| `src/system/libself_ptl/src/method.cpp` | get 类回调调用方式调整 | +| `src/system/libcom_decode/src/decode_frame_codec.cpp` | 更新 `icp67_show_frame()` 路径引用 | + +--- + +## 任务分解 + +### T1: 添加常量宏定义 + +**文件**: `release/inc/myIcp67.h`、`src/protocol/libicp67/inc/icp67.h` + +在 `myIcp67.h` 中新增: +```c +#define ICP67_TX_BUF_SIZE 2048 // tx/resend_tx 缓冲区大小 +#define ICP67_RESEND_MAX 5 // 重发最大次数 +#define ICP67_TM_TICK_MS 10 // 定时器 tick 周期 (ms) +#define ICP67_TM_OUT_MS 1000 // 重传超时 (ms) +#define ICP67_MD5_LEN 16 // MD5 长度 +``` + +在 `icp67.h` 中新增: +```c +#define ICP67_HEAD_OVERHEAD 4 // head1(1)+len(2)+head2(1) +#define ICP67_FRAME_OVERHEAD 6 // head_overhead(4)+crc(1)+tail(1) +#define ICP67_UPGRADE_TYPE 1 // 升级类型 +#define ICP67_NAME_MAX 256 // 文件名最大长度 +#define ICP67_TM_STRUCT_LEN 7 // 时间结构体长度 +``` + +将所有魔数替换为宏或 `sizeof()`(`pos += 4` → `pos += sizeof(uint32_t)`; `pos += 2` → `pos += sizeof(uint16_t)`;`16` → `ICP67_MD5_LEN` 等)。 + +`stru_icp67` 中的 `tx[ICP67_TX_MAX_LEN]`、`resend_tx[ICP67_TX_MAX_LEN]` 改为 `[ICP67_TX_BUF_SIZE]`,`md5[16]` 改为 `md5[ICP67_MD5_LEN]`。 + +--- + +### T2: 将 stru_genneral_method 移入 stru_icp67 + +**文件**: `release/inc/myIcp67.h` + +在 `stru_icp67` 结构体中添加字段: +```c +typedef struct _icp67 +{ + void *arg; + 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; // ← 新增,替代全局 g_genneral_method + + uint8_t md5[ICP67_MD5_LEN]; + uint8_t tx[ICP67_TX_BUF_SIZE]; + // ... 其余不变 +}icp67; +``` + +--- + +### T3: 重构 setter/getter 为实例化接口 + +**文件**: `src/protocol/libicp67/src/general_method.cpp`、`release/inc/myIcp67.h` + +**变更**: + +1. **删除** `g_genneral_method` 全局变量和 `icp67_get_genneral_method()` 函数。 + +2. **删除** `general_method.h` 文件(不再需要 `icp67_get_genneral_method()` 前向声明)。 + +3. **"pop_out/trans" 类 setter**(17个):参数增加 `stru_icp67 *p_icp67`,写入 `p_icp67->method.xxx_cb`。示例: + ```c + void icp67_set_mx_trans_cb(stru_icp67 *p_icp67, icp67_mx_trans_cb cb) { + p_icp67->method.mx_trans_cb = cb; + } + ``` + +4. **"get" 类 setter**(12个):不再从全局表"拉取"到 caller 结构体。改为让 caller 直接通过 `p_icp67->method.xxx_cb()` 调用。这些 setter 变为空操作或删除——caller 直接访问 `g_self_ptl.icp67.method.ao_get_cb(...)`。 + +5. **更新 `myIcp67.h` 中所有 extern 声明**:增加 `stru_icp67 *p_icp67` 第一参数。"get" 类 12 个 setter 删除声明。 + +6. **method 初始化**:在 `icp67_init()` 中将 `p_icp67->method` 的 sender 字段初始化为内部函数指针,pop_out/trans 字段初始化为 NULL。 + ```c + // icp67_init 中新增 + p_icp67->method.ao_get_cb = icp67_ao_get; + p_icp67->method.ao_set_cb = icp67_ao_set; + // ... 13 个 sender 初始化 + ``` + +7. **将 internal sender 函数**从 `LOCAL` 改为公开(或提供 `extern` 声明),以便 `icp67_init` 可以引用它们。在 `icp67.cpp` 中声明: + ```c + extern void icp67_ao_get(stru_icp67 *p, stru_ti_1_2_data *d, uint16_t n); + extern void icp67_ao_set(stru_icp67 *p, uint8_t *d, uint16_t n); + // ... 13个 + ``` + +8. **更新 `general_method.cpp`**:删除 `g_genneral_method` 初始化代码,将 13 个 sender 函数删除 `LOCAL`(或使用条件编译保留 static 内部链接,在 icp67.cpp 中使用函数指针表初始化)。 + +--- + +### T4: 重构 decode 函数——从 instance 读回调 + +**文件**: `src/protocol/libicp67/src/icp67.cpp` + +所有 decode 函数中,将: +```c +stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); +p_genneral_method->ao_pop_out_cb(...); +``` +改为: +```c +p_icp67->method.ao_pop_out_cb(...); +``` + +涉及 16 个 decode 函数。移除 `#include "general_method.h"`。 + +--- + +### T5: 修复重传竞态(Bug 1) + +**文件**: `src/protocol/libicp67/src/icp67.cpp`,`icp67_timer_handler()`(~line 960-983) + +将 `resend_cnt++` 和 `tm_cnt = 0` 从信号量外移入保护区内: + +**方案**:在 `icp67_rtx_flag_set` 中增加参数控制 resend 递增,或在 timer handler 中通过一个新的受保护操作完成。 + +**推荐方案**:在 `icp67_rtx_flag_set` 增加重载或新函数 `icp67_rtx_resend_inc(stru_icp67 *p_icp67)`: +```c +void icp67_rtx_resend_inc(stru_icp67 *p_icp67) { + sem_wait(&p_icp67->rtx_sem); + p_icp67->resend_cnt++; + p_icp67->tm_cnt = 0; + sem_post(&p_icp67->rtx_sem); +} +``` +timer handler 中调用此函数而非直接操作字段。`tm_cnt++`(line 982)也移入 `rtx_sem` 保护: +```c +void icp67_rtx_tm_inc(stru_icp67 *p_icp67) { + sem_wait(&p_icp67->rtx_sem); + p_icp67->tm_cnt++; + sem_post(&p_icp67->rtx_sem); +} +``` +timer handler 调用: +```c +icp67_rtx_tm_inc(p_icp67); +icp67_rtx_flag_get(p_icp67, rtx_flag, resend_cnt, tm_cnt); +if (rtx_flag == ICP67_TX_FLAG && resend_cnt < ICP67_RESEND_MAX && tm_cnt >= p_icp67->tm_out) { + p_icp67->send_cb(p_icp67->resend_tx, p_icp67->resend_tx_len, p_icp67->arg); + icp67_rtx_resend_inc(p_icp67); + LOG_I("resend cnt %d", p_icp67->resend_cnt); + icp67_show_frame(p_icp67->resend_tx, p_icp67->resend_tx_len); +} +``` + +--- + +### T6: 发送新请求覆盖旧 resend_tx 防御(Bug 3) + +**文件**: `src/protocol/libicp67/src/icp67.cpp`,`icp67_rtx_flag_set()` + +在函数内增加 LOG_W 防御: +```c +void icp67_rtx_flag_set(stru_icp67 *p_icp67, uint8_t flag, uint8_t resend_cnt, uint32_t tm_cnt) +{ + sem_wait(&p_icp67->rtx_sem); + if (flag == ICP67_TX_FLAG && p_icp67->rtx_flag == ICP67_TX_FLAG) { + LOG_W("icp67_rtx_flag_set: overwriting pending TX, prev resend_cnt=%d", p_icp67->resend_cnt); + } + p_icp67->rtx_flag = flag; + p_icp67->resend_cnt = resend_cnt; + p_icp67->tm_cnt = tm_cnt; + if (flag == ICP67_TX_FLAG) { + memcpy(p_icp67->resend_tx, p_icp67->tx, p_icp67->tx_len); + p_icp67->resend_tx_len = p_icp67->tx_len; + } + sem_post(&p_icp67->rtx_sem); +} +``` + +--- + +### T7: 填充空桩函数 + +**文件**: `src/protocol/libicp67/src/icp67.cpp` + +**TI_4** (`icp67_decode_ti_4`, line 196-199): +```c +LOCAL int icp67_decode_ti_4(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len) { + LOG_W("TI_4 not supported"); + icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0); + return 0; +} +``` + +**TI_203** (`icp67_decode_ti_203`, line 434-437): +```c +LOCAL int icp67_decode_ti_203(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len) { + LOG_W("TI_203 not supported"); + icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0); + return 0; +} +``` + +**TI_206**:保持死代码不变(不注册到 map,不删除)。 + +--- + +### T8: 更新调用方 self_ptl + +**文件**: `src/system/libself_ptl/src/self_ptl.cpp`、`inc/method.h`、`src/method.cpp` + +**self_ptl.cpp** (`self_ptl_init()` 函数): + +1. **"pop_out/trans" 类**(17个):每个setter 增加 `p_icp67` 第一参数: + ```c + icp67_set_ao_pop_out_cb(p_icp67, p_method->ao_pop_out_cb); + icp67_set_iec_point_tbl_pop_out_cb(p_icp67, p_method->iec_point_tbl_pop_out_cb); + // ... 17个 + ``` + +2. **"get" 类**(12个):原本通过 `icp67_set_xxx_cb(&p_method->xxx)` 从全局表"拉取"。删除这些调用。调用方式改为直接通过 `p_icp67->method.xxx_cb()`: + - 原来 `g_self_ptl.method.ao_get_cb(p_icp67, ...)` → 不变(method 中仍存储回调,但现在 icp67_init 直接把函数指针写入 p_icp67->method) + - 实际上 `g_self_ptl.method` 中存储的就是从旧全局表拉取的指针。现在改为让 callers 通过 `g_self_ptl.icp67.method.ao_get_cb(...)` 调用。 + +3. 从 `self_ptl_init()` 删除 12 个 get 类 setter 调用,并移除 `g_self_ptl.method` 中 receiver 组字段的初始化赋值——改为直接从 `p_icp67->method` 读取。 + +**method.cpp**:所有通过 `p_method->xxx_cb(p_icp67, ...)` 的调用改为 `p_icp67->method.xxx_cb(p_icp67, ...)`。 + +--- + +### T9: 更新 libcom_decode 引用 + +**文件**: `src/system/libcom_decode/src/decode_frame_codec.cpp` + +仅包含 `myIcp67.h` 使用 `stru_head` 定义和 `icp67_show_frame()`。移除 `#include "general_method.h"` 如果存在。`icp67_show_frame()` 调用确认是否受影响(此函数在 `icp67.cpp` 中为 `LOCAL`,外部不可见——需确认正确的调用路径。若 `decode_frame_codec.cpp` 调用它,需将其改为公开)。 + +--- + +### T10: 编译验证 + +```bash +./release/build.sh +``` + +确认 `libicp67.a` 构建成功、`RTU` 链接成功。 + +--- + +## 验证方法 + +1. 编译:`./release/build.sh` 通过,输出 `release/x86/exe/RTU` +2. 确认无新增 warning(`-Wall -Wextra` 级别) +3. 代码审查确认: + - `g_genneral_method` 全部消失 + - `icp67_get_genneral_method()` 全部消失 + - decode 函数全部通过 `p_icp67->method.xxx_cb` 回调 + - 重传竞态已修复(字段操作在 sem 内) + - 所有魔数替换为命名常量 + - TI_4/TI_203 有 LOG_W + RX_FLAG 设置 diff --git a/mimo/plan/iec101帧搜索方案.md b/mimo/plan/iec101帧搜索方案.md new file mode 100644 index 0000000..da2b7dc --- /dev/null +++ b/mimo/plan/iec101帧搜索方案.md @@ -0,0 +1,31 @@ +# IEC-101 帧搜索方案(修订) + +## 设计 + +在现有 `self_ptl_search_iec_frame()` 中增加 IEC-101 搜索分支,**由上到下串行匹配,命中即退出**: + +``` +self_ptl_search_iec_frame(p_data, len, p_pos, p_valid_len): + for i in 0..len: + ① 尝试 IEC-101 短帧 (0x10) + 0x10 | ctrl | addr(LSB) | [addr(MSB)] | cks | 0x16 + → 5或6字节,校验 cks = data 累加和 + ② 尝试 IEC-101 长帧 (0x68) + 0x68 | len | len | 0x68 | ctrl | addr(2B) | data.. | cks | 0x16 + → 验证 len重复 + 第4位0x68 + tail 0x16 + cks + ③ 尝试 IEC-104 帧 (0x68) — 保持现有逻辑 + 0x68 | len | ctrl1..4 | asdu.. + 排除:若满足 101 长帧特征则跳过(len重复+第4位=0x68) +``` + +## 涉及文件 + +| 文件 | 改动 | +|------|------| +| `self_ptl.cpp` | 修改 `self_ptl_search_iec_frame()` 增加 101 分支 | + +## 编译验证 + +```bash +./release/build.sh +``` diff --git a/mimo/plan/self_ptl缺陷优化方案.md b/mimo/plan/self_ptl缺陷优化方案.md new file mode 100644 index 0000000..c08ed81 --- /dev/null +++ b/mimo/plan/self_ptl缺陷优化方案.md @@ -0,0 +1,34 @@ +# Self_PTL 剩余缺陷优化方案 + +## 🔴 高优先级 + +### T1: D4 测试命令分离 +**文件**: `self_ptl.cpp:985-988`, `method.cpp:1061-1074` + +`self_ptl_method_task()` 每 TIMER2 tick 无条件执行,迭代 g_map_local_test。 +优化:增加 `g_self_ptl_test_active` 标志,仅当 cmd_self_ptl 触发测试时才在 TIMER2 中调用。 + +### T2: D2 环形缓冲保护 +**文件**: `self_ptl.cpp:98-139` + +当前 put/get 在同一线程,但无保护。增加 pthread_mutex_t 到 stru_self_rx 中。 + +## 🟡 中优先级 + +### T3: D3 溢出日志 +**文件**: `self_ptl.cpp:117` + +取消注释 LOG_E,增加 overflow_cnt 计数。 + +### T4: D8 SBO 超时 +涉及 `stru_signal_ctrl` + `dc_signal.cpp`,范围较广需确认。 + +## 🟢 低优先级 + +### T5: D6 硬编码 +**文件**: `self_ptl.cpp` + +2048/256 → 命名 #define。 + +### T6: D7 双缓冲 +改动大,暂缓。 diff --git a/mimo/工程/libicp67模块分析.md b/mimo/工程/libicp67模块分析.md new file mode 100644 index 0000000..8df37d2 --- /dev/null +++ b/mimo/工程/libicp67模块分析.md @@ -0,0 +1,153 @@ +# libicp67 协议库分析文档 + +## 1. 模块概述 + +**路径**: `src/protocol/libicp67/` + +**定位**: ICP67 二进制协议库——用于维护软件与 RTU/FTU 自侧之间、以及主板与采样板之间通信的私有协议引擎。负责帧定界、编解码、重传管理。 + +**文件结构**: +``` +src/protocol/libicp67/ +├── inc/ +│ ├── icp67.h -- TI/COT 常量、帧 ASDU 结构体 +│ └── general_method.h -- icp67_get_genneral_method() 前向声明 +└── src/ + ├── icp67.cpp -- 核心:搜帧、解码分发、初始化、组帧、重传 + └── general_method.cpp -- 回调 setter、默认 sender 实现 + +release/inc/myIcp67.h -- 共享契约:stru_head、stru_icp67、stru_genneral_method +``` + +## 2. 协议帧格式 + +``` +| 0x67 | len(2B) | 0x67 | src | dst | dir | ti | cot | info_addr(2B) | dev_addr(4B) | data... | CRC(1B) | 0x16 | +| 帧头1 | 长度 | 帧头2 | 源 | 目的 | 方向 |类型| 传送原因 | 信息体地址 | 设备地址 | 数据体 | 校验和 | 帧尾 | +``` + +- **TI (Type Identifier)**: 16 种消息类型 (TI_1 ~ TI_207) +- **COT (Cause of Transmission)**: 请求(5)、激活(6)、正常确认(7)、终端响应(8)、MD5不匹配(20) +- **校验**: 8-bit 累加校验和 (data 部分) +- **设备地址**: src/dst 取值:1=维护软件, 2=主板, 3=采样板, 4=LCD, 5=XTU + +## 3. 核心数据结构 + +### 3.1 `stru_head` (1字节对齐) +帧头结构,包含所有固定头部字段 + 可变数据区。`len` 字段为 `info_addr` + `dev_addr` + `data[...]` 的总长度。 + +### 3.2 `stru_icp67` —— 协议实例 +| 字段 | 用途 | +|------|------| +| `send_cb` / `search_frame_cb` / `decode_cb` / `timer_handler_cb` | 四个对外回调 | +| `tx[2048]` / `tx_len` | 发送缓冲区 | +| `resend_tx[2048]` / `resend_tx_len` | 重发备份缓冲区 | +| `rtx_flag` / `rtx_sem` / `resend_cnt` / `tm_out` / `tm_cnt` | 重传状态机 | +| `md5[16]` | AO 参数 MD5 校验值 | +| `arg` | 用户数据 (libself_ptl 传入 interface ID) | + +### 3.3 `stru_genneral_method` —— 全局回调表 +26 个函数指针,分为两组: +- **sender 组** (13个): ao_get, ao_set, iec_point_tbl_get, time_set, self_check_get, upgrade_start, dir_read, file_read_act/confirm, file_write_act/write/write_end_confirm +- **receiver 组** (13个): 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 + +## 4. 核心函数 + +### 4.1 `icp67_init(p, send_cb, arg)` +绑定 `send_cb`、`search_frame_cb`(→icp67_search_frame)、`decode_cb`(→icp67_decode)、`timer_handler_cb`(→icp67_timer_handler)。初始化重传信号量、TM 周期(100)、重发计数(0)。 + +### 4.2 `icp67_search_frame(p_rx, rx_len, p_pos, p_len)` +帧定界器:扫描 `0x67 0x67`,验证长度边界、CRC 校验和、帧尾 `0x16`。返回帧位置和有效长度。 + +### 4.3 `icp67_decode(p_icp67, p_data, len)` +顶层解码分发器:从帧头读取 `ti`,查 `g_map_ti_decode` 映射表,调用对应的 `icp67_decode_ti_{N}` 函数。 + +### 4.4 `icp67_timer_handler(p_icp67)` +重传定时器:TX_FLAG 状态下,每 tick `tm_cnt++`,达到 `tm_out`(100 tick ≈ 1000ms) 且重发次数 < 5 时,重新发送 `resend_tx`。超过 5 次清除 TX_FLAG。 + +### 4.5 各 TI 解码函数 +- TI_1: 读参数响应 → `ao_pop_out_cb` +- TI_2: 写参数响应 (无数据,仅确认) +- TI_3: 读 IEC 点表响应 (支持分帧) → `iec_point_tbl_pop_out_cb` +- TI_4: 写 IEC 点表响应 (空桩) +- TI_5: 对时响应 +- TI_6: 自检响应 → `self_check_pop_out_cb` +- TI_9: 升级响应 +- TI_11: 文件操作分发 (9种子命令) +- TI_30: ZIP 波形分发 (4种子命令) +- TI_200: MX 遥测传输 → `mx_trans_cb` +- TI_201: ST 遥信传输 → `st_trans_cb` +- TI_202: DD 电度传输 → `dd_trans_cb` +- TI_203: 遥控 (空桩) +- TI_204: SOE 事件 → `soe_trans_cb` +- TI_205: 故障事件 → `fault_trans_cb` +- TI_207: 测量扰动 → `mx_change_cb` + +## 5. 与 libself_ptl 的交互 + +``` + ┌─── icp67_init() 初始化 ───┐ + │ │ + libself_ptl ◄────► g_genneral_method (26回调) ◄────► libicp67 + (应用层) ├─ sender: self → icp67 │ (协议引擎) + └─ receiver: icp67 → self │ + │ + self_ptl_data_rx ──► search_frame_cb ──► decode_cb ──► method回调 ──► 数据中心 + self_ptl_data_tx ◄── send_cb ◄── frame builder (sender函数) +``` + +## 6. 优缺点分析 + +### 6.1 优点 + +| # | 优点 | 说明 | +|---|------|------| +| A1 | **协议与业务分离** | 通过回调表实现清晰的分层架构,ICP67 库不依赖任何上层模块 | +| A2 | **TI-COT 状态机完整** | 覆盖 16 种消息类型,支持请求/确认/响应等完整交互模式 | +| A3 | **重传机制** | 内置超时重传 (5次×1s),保障可靠通信 | +| A4 | **分帧支持** | TI_3 (IEC 点表) 支持多帧数据传输,带帧序号和续传标志 | +| A5 | **帧格式校验完善** | 帧头 0x67×2 + 长度验证 + CRC + 帧尾 0x16,五重保障 | +| A6 | **MD5 参数校验** | 参数读写带 MD5 校验,防止配置不匹配 | + +### 6.2 缺点 + +| # | 缺点 | 严重程度 | 说明 | +|---|------|----------|------| +| D1 | **全局单例回调表** | 🔴 高 | `g_genneral_method` 是全局变量,多实例场景下无法使用。`stru_icp67` 虽有实例字段但 decode 回调全部走全局表 | +| D2 | **空桩函数** | 🟡 中 | TI_4 (写IEC点表响应)、TI_203 (遥控) 等为空实现,功能不完整 | +| D3 | **重传设计粗糙** | 🟡 中 | 只备份最后一条发送帧,并发场景下只维护一个序列号;重传期间收到响应会误清 flag | +| D4 | **CRC 校验弱** | 🟡 中 | 8-bit 累加和,容易碰撞,不适合工业环境的长帧 | +| D5 | **回调设置侵入式** | 🟡 中 | sender 回调的 setter 通过写函数指针体覆盖默认实现,对 callback 未设置的路径静默失败 | +| D6 | **硬编码参数** | 🟢 低 | 缓冲区 2048、重试 5 次、超时 1000ms、设备地址硬编码,缺乏配置入口 | +| D7 | **无帧序号/去重** | 🟢 低 | 无应用层帧序号,重复帧/乱序帧无法检测 | +| D8 | **C 风格内存操作** | 🟢 低 | 大量 `memcpy`、裸指针运算、默认结构体 pack(1) 对齐,跨平台移植有隐患 | + +## 7. 改进方向与措施 + +### 7.1 架构改进 + +| 方向 | 措施 | 优先级 | +|------|------|--------| +| **去全局化** | 将 `g_genneral_method` 移入 `stru_icp67`,decode 函数通过 `p_icp67->method.xxx_cb` 回调;setter 改为 `icp67_set_xxx(p_icp67, cb)` | 🔴 高 | +| **状态机重构** | 引入独立的类/结构体管理多路请求状态 (request_id + state + timer),替代当前单一的 `rtx_flag/resend_cnt/tm_cnt` 三元组 | 🟡 中 | + +### 7.2 协议增强 + +| 方向 | 措施 | 优先级 | +|------|------|--------| +| **CRC 升级** | 8-bit 累加和替换为 CRC-16/CRC-CCITT,向后兼容可保留 CRC8 但增加 CRC16 字段 | 🟡 中 | +| **帧序号** | 在帧头增加 1 字节 frame_seq,发送端递增,接收端检测重复和丢帧 | 🟢 低 | +| **填充空桩** | 实现 TI_4、TI_203 的空桩函数,至少返回 NOT_SUPPORTED 确认 | 🟢 低 | +| **可配置参数** | 超时、重试次数、缓冲区大小通过 `icp67_init` 参数传入,存储在 `stru_icp67` 中 | 🟢 低 | + +### 7.3 代码质量 + +| 方向 | 措施 | 优先级 | +|------|------|--------| +| **消除硬编码** | 用 `#define`/`constexpr` 替代魔数 (0x67, 0x16, 2048, 5, 100 等),统一放到 `icp67.h` | 🟡 中 | +| **回调返回值** | sender 回调统一返回 `int` (0=成功),decode 回调失败时返回错误码给应用层,替代静默吞错 | 🟡 中 | +| **打包兼容** | `pack(1)` 改为显式 `uint8_t` 数组 + 序列化/反序列化函数,消除跨平台对齐风险 | 🟢 低 | + +## 8. 总结 + +`libicp67` 是一个功能完整但架构老旧的嵌入式协议库。核心编解码和重传逻辑是可靠的,主要问题集中在**全局单例耦合**和**可配置性不足**两个层面。最高优先级的改进是将全局回调表实例化,使其从"单设备绑定"升级为"多实例可复用"的协议引擎,从而支撑多通道场景(主板与多采样板同时通信)。 diff --git a/mimo/工程/libself_ptl模块分析.md b/mimo/工程/libself_ptl模块分析.md new file mode 100644 index 0000000..238e65b --- /dev/null +++ b/mimo/工程/libself_ptl模块分析.md @@ -0,0 +1,232 @@ +# libself_ptl 自协议层分析文档 + +## 1. 模块概述 + +**路径**: `src/system/libself_ptl/` + +**定位**: 自协议层——RTU/FTU 系统中连接 ICP67 协议库与数据中心的上层集成模块。负责协议初始化、双协议帧解复用 (ICP67 + IEC-104)、信号注册、数据收发调度。 + +**文件结构**: +``` +src/system/libself_ptl/ +├── inc/ +│ ├── self_ptl.h -- 帧类型定义、配置数据结构 +│ └── method.h -- 回调函数声明、局部辅助类型 +└── src/ + ├── self_ptl.cpp -- 核心:初始化、帧处理、信号注册、任务主循环 + └── method.cpp -- 回调实现:AO、IEC点表、文件操作、SOE/故障/MX/ST/DD 传输处理 + +src/system/RTU/src/self_ptl_cfg.cpp -- XML 配置解析 +test/config/SELF_PTL/self_ptl.xml -- 测试用 XML 配置 (790+ 信号) +``` + +## 2. 核心数据结构 + +### 2.1 `stru_self_rx` —— 环形缓冲区 +```c +typedef struct { + uint16_t rptr; // 读指针 + uint16_t wptr; // 写指针 + uint16_t size; // 缓冲区大小 (2048) + uint16_t cnt; // 有效数据计数 + uint8_t buf[2048]; // 数据缓冲区 +} stru_self_rx; +``` +用于原始字节流的 FIFO 缓冲,支持循环覆盖写。 + +### 2.2 `stru_self_ptl` —— 全局单例 +```c +typedef struct { + uint32_t interface; // 通信通道 ID + stru_icp67 icp67; // 嵌入的 ICP67 协议实例 + stru_genneral_method method; // 回调表本地副本 + stru_self_rx icp67_rx; // ICP67 原始帧接收缓冲 + stru_self_rx iec_rx; // IEC-104 原始帧接收缓冲 + uint8_t temp_buf[2048]; // 临时缓冲区 +} stru_self_ptl; +``` + +### 2.3 配置数据结构 (`self_ptl.h`) +| 结构 | 用途 | +|------|------| +| `stru_self_ptl_cfg_base_data` | 运行时绑定: `p_base`(配置) → `p_data`(值) → `p_ctrl`(SBO控制) | +| `stru_self_ptl_cfg_param_data` | AO/Param 绑定: 配置 + SBO + 值向量 + 默认值向量 | +| `stru_self_ptl_cfg_data` | 完整配置容器: st_vec, mx_vec, co_vec, dd_vec, ao_vec, param_vec | + +### 2.4 局部辅助类型 (`method.h`) +| 结构 | 用途 | +|------|------| +| `stru_tlv` | TLV 编码: type + len + val[64] | +| `stru_dir_info` | 文件目录项: name[256], len, attr, size | +| `stru_local_ao_get` | AO 读取分帧状态: rx_cnt, tx_cnt, per_cnt, offset | +| `stru_local_file` | 文件操作上下文: sub_cmd, temp_str, dir_name, file_name | +| `stru_local_zip_info` | ZIP 传输状态: zip_type, zip_name, file_num, file_info[2] | + +## 3. 核心流程 + +### 3.1 初始化流程 + +``` +app_self_ptl_init1() + ├── self_ptl_init() + │ ├── icp67_init(&g_self_ptl.icp67, self_ptl_data_tx, &interface) + │ ├── icp67_set_ao_cfg_md5() // 加载 AO 参数 MD5 + │ ├── 方向A: icp67_set_{sender}_cb() × 13 → g_genneral_method.sender + │ └── 方向B: icp67_set_{receiver}_cb() × 13 → g_genneral_method.receiver + ├── self_ptl_cfg_init() // 解析 XML 配置 + └── self_ptl_do_signal_out() + ├── dc_signal_out() × ST数量 // 注册遥信信号 + ├── dc_signal_out() × MX数量 // 注册遥测信号 + ├── dc_signal_yk() × CO数量 // 注册遥控信号 + ├── dc_signal_out() × DD数量 // 注册电度信号 + ├── dc_signal_ao() × AO数量 // 注册参数信号 + └── dc_signal_param() × Param数量 // 注册定值信号 +``` + +### 3.2 数据接收流程 + +``` +app_self_ptl (RTOS 任务) + ├── wait(EV_SELF_PTL_RX_COM) + └── self_ptl_data_rx(p_data) + ├── 解析 stru_msg_head (interface + len) + └── self_ptl_search_frame(p_rx, len, p_icp67) + ├── put_rx_data() → icp67_rx 环形缓冲 + ├── put_rx_data() → iec_rx 环形缓冲 + ├── do while: + │ ├── icp67.search_frame_cb() → icp67_search_frame() + │ │ └── 搜到帧 → icp67.decode_cb() → g_genneral_method.*_cb → 数据中心 + │ └── self_ptl_search_iec_frame() + │ └── 搜到 IEC-104 帧 → msg_send() → COM 层 + └── 滑窗: 第一个 0x66/0x68 之前的数据丢弃 +``` + +### 3.3 IEC-104 帧处理 + +`self_ptl_search_iec_frame()` 负责识别 IEC-104 帧: +1. 检查 APCI 起始字节 `0x68` +2. 检查 ASDU 完整性 (非零 TI, 非零 VSQ, 有效 COT) +3. 分类为 I 帧 (编号数据传输)、S 帧 (编号确认)、U 帧 (控制功能) 或 ERR_FRAME +4. 有效帧转发到 COM 消息队列 `MQ_SELF_PTL_TO_COM` + +### 3.4 数据发送流程 + +``` +(应用层触发) + └── self_ptl_signal_change_callback() + └── g_self_ptl.method.ao_set_cb(p_icp67, data, cnt) + └── icp67_ao_set() → 构建 TI_2 帧 + └── p_icp67->send_cb() → self_ptl_data_tx() + └── 包装 stru_msg_head → msg_send(MQ_SELF_PTL_TO_COM) +``` + +### 3.5 定时任务 + +``` +app_self_ptl (RTOS 任务) + ├── wait(EV_TIMER1/2/3) + ├── self_ptl_task() // 调用 icp67.timer_handler_cb → 重传 + └── self_ptl_method_task() // 测试命令驱动 (g_flag[]) + ├── test_ao_get() → 读取 AO 参数 + ├── test_iec_point_tbl_get() → 读取 IEC 点表 + ├── test_time_set() → 对时 + ├── test_self_check() → 自检 + ├── test_upgrade() → 升级 + └── test_file() → 文件操作 (目录/读写) +``` + +## 4. 双协议共信道机制 + +`libself_ptl` 的核心设计之一是**同一物理通道同时承载 ICP67 和 IEC-104 两种协议帧**: + +``` + ┌─── icp67_rx (环形缓冲) ──► icp67_search_frame ──► ICP67 decode + / +raw bytes → self_ptl_search_frame + \ + └─── iec_rx (环形缓冲) ──► self_ptl_search_iec_frame ──► COM 转发 +``` + +- 两种协议的帧被同时写入各自的环形缓冲区 +- 帧搜索交替进行:先搜 ICP67 帧,再搜 IEC-104 帧 +- IEC 帧不经过 ICP67 decode,直接转发到 IEC-104 协议栈所在的通信模块 +- 各自缓冲区独立滑窗,互不干扰 + +## 5. 与 libicp67 的耦合关系 + +``` +g_self_ptl.icp67 ←── icp67_init() ──→ icp67 协议实例 + ├─ send_cb → self_ptl_data_tx() + ├─ search_frame_cb → icp67_search_frame() + ├─ decode_cb → icp67_decode() + └─ timer_handler_cb → icp67_timer_handler() + +g_genneral_method ←───────────────── icp67_set_*_cb() × 26 + ├─ [sender 组] method { ao_get, ao_set, iec_point_tbl_get, ... } + └─ [receiver 组] method { mx_trans, st_trans, soe_trans, fault_trans, ... } +``` + +## 6. 优缺点分析 + +### 6.1 优点 + +| # | 优点 | 说明 | +|---|------|------| +| A1 | **双协议解复用** | 在同一物理通道上同时承载 ICP67 和 IEC-104,通过双环形缓冲区实现协议帧分离 | +| A2 | **回调式架构** | 完整的回调驱动模型,协议解码与业务处理解耦,新增 TI 类型只需实现回调 | +| A3 | **配置驱动** | 信号表通过 XML 加载,无需修改代码即可调整遥信/遥测/遥控/电度/参数/定值 | +| A4 | **SBO (选择-执行)控制** | 遥控和参数写入支持 select-before-operate 安全机制 | +| A5 | **文件传输支持** | 完整的 ZIP 波形和通用文件传输流程 (目录→读取/写入→确认→MD5校验) | +| A6 | **AO 参数 MD5** | 读取回参数时 MD5 校验防配置不一致 | +| A7 | **RTOS 任务模型** | 事件驱动的事件+定时器双驱任务,低 CPU 占用 | + +### 6.2 缺点 + +| # | 缺点 | 严重程度 | 说明 | +|---|------|----------|------| +| D1 | **全局单例 `g_genneral_method`** | 🔴 高 | ICP67 的 decode 回调全部走全局表,导致多 ICP67 实例 (如主板同时连接多个采样板) 无法独立工作,所有实例的回调被最后一组 setter 覆盖 | +| D2 | **环形缓冲无锁保护** | 🔴 高 | `stru_self_rx` 在 ISR (生产者) 和 task (消费者) 间共享,无临界区保护,存在竞态风险 | +| D3 | **缓冲区溢出处理粗暴** | 🟡 中 | 环形缓冲溢出时仅输出 LOG,数据被静默丢弃且无计量统计 | +| D4 | **测试命令耦合** | 🟡 中 | `self_ptl_method_task()` 中硬编码了测试命令序列 (ao_get → iec_point_tbl_get → time_set → self_check → upgrade → file),生产代码中混入调试逻辑 | +| D5 | **IEC-104 帧判断粗糙** | 🟡 中 | `self_ptl_search_iec_frame()` 仅检查 0x68 起始 + 简单字段完整性,对 APCI 控制域未做完整的 I/S/U 帧状态管理 | +| D6 | **硬编码参数** | 🟢 低 | 环形缓冲大小(2048)、临时缓冲区(2048)硬编码,无配置入口 | +| D7 | **双缓冲复制冗余** | 🟢 低 | 每次搜帧先 `get_rx_data()` 拷贝整个缓冲区,再 `memcpy` 帧数据到 `temp_buf`,存在双重拷贝开销 | +| D8 | **错误处理不足** | 🟢 低 | 多数回调失败仅 LOG,不向上层返回错误状态;SBO 控制无超时自动取消 | +| D9 | **滑窗丢弃策略** | 🟢 低 | `icp66_search_first_head()` 丢弃帧头前的所有字节,若两帧间误入一个 0 字节会把整帧丢失 | + +## 7. 改进方向与措施 + +### 7.1 架构改进 + +| 方向 | 措施 | 优先级 | +|------|------|--------| +| **回调实例化** | 将 `g_genneral_method` 移入 `stru_icp67`,decode/send 回调从实例字段读取,使协议库支持多实例 | 🔴 高 | +| **生产/调试分离** | 将 `test_ao_get` 等测试命令通过编译宏 (`#ifdef SELF_PTL_TEST`) 隔离,或统一作为外部命令接口由 DC 触发 | 🔴 高 | +| **临界区保护** | 环形缓冲的 put/get/cnt 操作增加关中断/信号量保护,防止 ISR 与 task 竞态 | 🔴 高 | + +### 7.2 协议处理增强 + +| 方向 | 措施 | 优先级 | +|------|------|--------| +| **IEC-104 状态机** | 完善 I/S/U 帧的发送序列号和接收序列号管理,支持 APCI 层面的确认和窗口控制 | 🟡 中 | +| **缓冲区计量** | 增加 `overflow_cnt`、`discard_bytes` 统计字段,定期上报到数据中心 | 🟢 低 | +| **零拷贝优化** | `get_rx_data` 后的全量拷贝改为直接操作环形缓冲区的指针范围,减少一次拷贝 | 🟢 低 | + +### 7.3 可靠性增强 + +| 方向 | 措施 | 优先级 | +|------|------|--------| +| **SBO 超时** | SBO 选择后增加看门狗定时器 (如 30s),超时自动发送取消命令 | 🟡 中 | +| **错误码传递** | 所有回调统一返回 `int` 错误码,`self_ptl_data_rx` 统计成功/失败帧数并上报 | 🟡 中 | +| **滑动窗口改进** | `icp66_search_first_head` 改为仅跳过连续非帧头数据,保留帧头前至少 1 字节作为下一帧的候选起始 | 🟢 低 | + +### 7.4 可维护性 + +| 方向 | 措施 | 优先级 | +|------|------|--------| +| **常量集中管理** | 缓冲区大小、最大帧长、超时值统一为模块内 `constexpr` | 🟢 低 | +| **XML 配置解耦** | `self_ptl_cfg_init()` 中的 XML 类型判断逻辑改用策略模式/注册表,避免硬编码类型分支 | 🟢 低 | + +## 8. 总结 + +`libself_ptl` 作为 RTU/FTU 系统的协议集成层,承担了**双协议解复用**、**信号注册分发**、**回调桥接**三大核心职责。当前实现功能完备,但在线程安全和多实例扩展方面存在明显短板。最高优先级的三项改进——回调实例化、生产/调试分离、临界区保护——可以解决当前架构中最关键的可靠性和可扩展性问题。 diff --git a/mimo/问题处理文档.md b/mimo/问题处理文档.md index d821078..196b5ef 100644 --- a/mimo/问题处理文档.md +++ b/mimo/问题处理文档.md @@ -2,8 +2,33 @@ --- -## 2026-06-15 +## 2026-06-16: ICP67 模块多实例重构 +**来源**:[libicp67模块分析](./工程/libicp67模块分析.md) + +### 修复项 + +1. **全局回调表单例化** — 将 `g_genneral_method` 从 static 全局变量移入 `stru_icp67.method`。26 个 setter 改为实例化接口(`stru_icp67 *` 第一参数)。删除 `general_method.h`、`icp67_get_genneral_method()`。所有 decode 函数改为 `p_icp67->method.xxx_cb` 回调。 + +2. **重传竞态修复** — `icp67_timer_handler` 中 `resend_cnt++`/`tm_cnt=0`/`tm_cnt++` 移入 `rtx_sem` 保护区。 + +3. **发送覆盖防御** — `icp67_rtx_flag_set` 增加 TX_FLAG 重复设置 LOG_E 警告。 + +4. **空桩填充** — `icp67_decode_ti_4`、`icp67_decode_ti_203` 改为 LOG_E + ICP67_RX_FLAG 设置。 + +5. **硬编码清理** — 所有魔数替换为命名宏(`ICP67_TX_BUF_SIZE`、`ICP67_MD5_LEN`、`ICP67_TM_TICK_MS`/`ICP67_TM_OUT_MS`、`ICP67_HEAD_OVERHEAD`/`ICP67_FRAME_OVERHEAD` 等)。 + +6. **配置参数宏化** — 超时/重试/缓冲/定时器 tick 统一在 `myIcp67.h` 中用 `#define` 管理。 + +7. **sender 函数迁移** — 12 个内部 sender 函数从 `general_method.cpp` 迁入 `icp67.cpp`,`icp67_init` 中初始化。 + +**状态**:✅ 已完成 +**涉及文件**:`myIcp67.h`, `icp67.h`, `icp67.cpp`, `general_method.cpp`, `self_ptl.cpp`, `method.cpp`, `general_method.h`(已删除) + +**设计决策**: +- pack(1) 不转换(ARM/x86 小端固定,风险收益比不成立) +- TI_11 len==11 注释不启(子函数已各自处理标志) +- dispatch map(`g_map_ti_decode` 等)保持 static(read-only,多实例安全) ### #11 libcom_channel + libcom_scan 合并为 libcom_decode **问题**:两个模块紧耦合(com_channel 调 com_recv_data,com_scan 调 com_channel_interface_get),且 app_comm_channel 线程为空壳 @@ -195,3 +220,31 @@ **涉及文件**:`ws_method.h`, `ws_method.cpp`, `web_server.cpp` --- + +--- + +## 2026-06-16: Self_PTL 缺陷优化 + +**来源**:[libself_ptl模块分析](./工程/libself_ptl模块分析.md) + +### 修复项 + +1. **D4 测试命令分离** — `self_ptl_method_task()` 增加 `g_self_ptl_test_active` 守卫,仅当 CLI 触发测试命令(`cmd_self_ptl` 设置 flag)时才进入遍历;TIMER2 先检查 active 标志再调用。 + +2. **D2 环形缓冲区加锁** — `stru_self_rx` 增加 `pthread_mutex_t mutex` 字段,`put_rx_data`/`get_rx_data` 操作加锁保护。 + +3. **D3 溢出日志启** — `put_rx_data` 溢出处理中原被注释的 `LOG_E` 已启。 + +4. **D8 SBO 超时** — `stru_signal_ctrl` 增加 `select_time_ms` + `sbo_timeout_ms` 字段。`dc_check_ctrl_valid` 在 SELECT 时记录时间戳。新增 `dc_signal_check_sbo_timeout()` 函数。`self_ptl_task()` 每定时器 tick 检查 SBO 状态,超时(默认 30s)自动回退到 READY。 + +5. **D6 硬编码清理** — `2048` → `SELF_PTL_BUF_SIZE`,`256` → `SELF_PTL_TEMP_SIZE`,IEC-104 APCI 魔数 → `IEC_APCI_MIN_LEN`/`IEC_FRAME_OVERHEAD`。 + +### 未处理 + +- **D7 双缓冲优化** — 改动大、风险高,暂缓。 +- **D5 IEC-104 帧校验** — 已完整,无需处理。 +- **D9 滑窗丢弃** — 逻辑正确,无需处理。 + +**状态**:✅ 已完成 +**涉及文件**:`self_ptl.cpp`, `method.cpp`, `myDatacenter.h`, `dc_signal.cpp` + diff --git a/release/inc/myIcp67.h b/release/inc/myIcp67.h index 493b996..cf1a10d 100644 --- a/release/inc/myIcp67.h +++ b/release/inc/myIcp67.h @@ -3,14 +3,17 @@ #include "myBase.h" #define ICP67_DEV_ADDR 1 -#define ICP67_TX_MAX_LEN 2048 +#define ICP67_TX_BUF_SIZE 2048 // tx/resend_tx 缓冲区大小 +#define ICP67_RESEND_MAX 5 // 重发最大次数 +#define ICP67_TM_TICK_MS 10 // 定时器 tick 周期 (ms) +#define ICP67_TM_OUT_MS 1000 // 重传超时 (ms) +#define ICP67_MD5_LEN 16 // MD5 长度 struct _icp67; typedef struct _icp67 stru_icp67; #define ICP67_RX_FLAG 0x01 #define ICP67_TX_FLAG 0x02 -#define ICP67_RESEND_MAX 5 #define DEV_MAINTENANCE_ADDR 0 // 维护软件设备地址 @@ -233,38 +236,26 @@ typedef struct }stru_genneral_method; -extern void icp67_set_ao_get_cb(icp67_ao_get_cb *p_cb); // 设置参数获取回调函数 -extern void icp67_set_ao_pop_out_cb(icp67_ao_pop_out_cb cb); // 设置参数数据返回回调函数 -extern void icp67_set_ao_set_cb(icp67_ao_set_cb *p_cb); // 设置参数设置回调函数 -extern void icp67_set_iec_point_tbl_get_cb(icp67_iec_point_tbl_get_cb *p_cb); // 设置iec点表获取回调函数 -extern void icp67_set_iec_point_tbl_pop_out_cb(icp67_iec_point_tbl_pop_out_cb cb); // 设置iec点表数据返回回调函数 -extern void icp67_set_time_set_cb(icp67_time_set_cb *p_cb); // 设置时间设置回调函数 -extern void icp67_set_self_check_get_cb(icp67_self_check_get_cb *p_cb); // 设置自检获取回调函数 -extern void icp67_set_self_check_pop_out_cb(icp67_self_check_pop_out_cb cb); // 设置自检数据返回回调函数 -extern void icp67_set_upgrade_start_cb(icp67_upgrade_start_cb *p_cb); // 设置升级开始回调函数 +extern void icp67_set_ao_pop_out_cb(stru_icp67 *p_icp67, icp67_ao_pop_out_cb cb); // 设置参数数据返回回调函数 +extern void icp67_set_iec_point_tbl_pop_out_cb(stru_icp67 *p_icp67, icp67_iec_point_tbl_pop_out_cb cb); // 设置iec点表数据返回回调函数 +extern void icp67_set_self_check_pop_out_cb(stru_icp67 *p_icp67, icp67_self_check_pop_out_cb cb); // 设置自检数据返回回调函数 -extern void icp67_set_dir_read_cb(icp67_dir_read_cb *p_cb); // 设置目录读取回调函数 -extern void icp67_set_dir_pop_out_cb(icp67_dir_pop_out_cb cb); // 设置目录数据返回回调函数 -extern void icp67_set_file_read_act_cb(icp67_file_read_act_cb *p_cb); // 设置读文件激活回调函数 -extern void icp67_set_file_read_act_confirm_cb(icp67_file_read_act_confirm_cb cb); // 设置读文件激活确认回调函数 -extern void icp67_set_file_read_cb(icp67_file_read_cb cb); // 设置读文件回调函数 -extern void icp67_set_file_read_confirm_cb(icp67_file_read_confirm_cb *p_cb); // 设置读文件确认回调函数 -extern void icp67_set_file_write_act_cb(icp67_file_write_act_cb *p_cb); // 设置写文件激活回调函数 -extern void icp67_set_file_write_act_confirm_cb(icp67_file_write_act_confirm_cb cb); // 设置写文件激活确认回调函数 -extern void icp67_set_file_write_cb(icp67_file_write_cb *p_cb); // 设置写文件回调函数 -extern void icp67_set_file_write_confirm_cb(icp67_file_write_confirm_cb cb); // 设置写文件确认回调函数 -extern void icp67_set_file_write_end_cb(icp67_file_write_end_cb cb); // 设置写文件结束回调函数 -extern void icp67_set_file_write_end_confirm_cb(icp67_file_write_end_confirm_cb *p_cb); // 设置写文件结束确认回调函数 +extern void icp67_set_dir_pop_out_cb(stru_icp67 *p_icp67, icp67_dir_pop_out_cb cb); // 设置目录数据返回回调函数 +extern void icp67_set_file_read_act_confirm_cb(stru_icp67 *p_icp67, icp67_file_read_act_confirm_cb cb); // 设置读文件激活确认回调函数 +extern void icp67_set_file_read_cb(stru_icp67 *p_icp67, icp67_file_read_cb cb); // 设置读文件回调函数 +extern void icp67_set_file_write_act_confirm_cb(stru_icp67 *p_icp67, icp67_file_write_act_confirm_cb cb); // 设置写文件激活确认回调函数 +extern void icp67_set_file_write_confirm_cb(stru_icp67 *p_icp67, icp67_file_write_confirm_cb cb); // 设置写文件确认回调函数 +extern void icp67_set_file_write_end_cb(stru_icp67 *p_icp67, icp67_file_write_end_cb cb); // 设置写文件结束回调函数 -extern void icp67_set_zip_dir_pop_out_cb(icp67_zip_dir_pop_out_cb cb); // 设置压缩目录数据返回回调函数 -extern void icp67_set_zip_file_pop_out_cb(icp67_zip_file_pop_out_cb cb); // 设置压缩文件数据返回回调函数 +extern void icp67_set_zip_dir_pop_out_cb(stru_icp67 *p_icp67, icp67_zip_dir_pop_out_cb cb); // 设置压缩目录数据返回回调函数 +extern void icp67_set_zip_file_pop_out_cb(stru_icp67 *p_icp67, icp67_zip_file_pop_out_cb cb); // 设置压缩文件数据返回回调函数 -extern void icp67_set_mx_trans_cb(icp67_mx_trans_cb cb); -extern void icp67_set_st_trans_cb(icp67_st_trans_cb cb); -extern void icp67_set_dd_trans_cb(icp67_dd_trans_cb cb); -extern void icp67_set_soe_trans_cb(icp67_soe_trans_cb cb); -extern void icp67_set_fault_trans_cb(icp67_fault_trans_cb cb); -extern void icp67_set_mx_change_cb(icp67_mx_change_cb cb); +extern void icp67_set_mx_trans_cb(stru_icp67 *p_icp67, icp67_mx_trans_cb cb); +extern void icp67_set_st_trans_cb(stru_icp67 *p_icp67, icp67_st_trans_cb cb); +extern void icp67_set_dd_trans_cb(stru_icp67 *p_icp67, icp67_dd_trans_cb cb); +extern void icp67_set_soe_trans_cb(stru_icp67 *p_icp67, icp67_soe_trans_cb cb); +extern void icp67_set_fault_trans_cb(stru_icp67 *p_icp67, icp67_fault_trans_cb cb); +extern void icp67_set_mx_change_cb(stru_icp67 *p_icp67, icp67_mx_change_cb cb); typedef struct _icp67 @@ -274,12 +265,13 @@ typedef struct _icp67 icp67_search_frame_cb search_frame_cb; icp67_decode_cb decode_cb; icp67_timer_handler_cb timer_handler_cb; - - uint8_t md5[16]; - uint8_t tx[ICP67_TX_MAX_LEN]; + stru_genneral_method method; + + uint8_t md5[ICP67_MD5_LEN]; + uint8_t tx[ICP67_TX_BUF_SIZE]; uint16_t tx_len; - uint8_t resend_tx[ICP67_TX_MAX_LEN]; + uint8_t resend_tx[ICP67_TX_BUF_SIZE]; uint16_t resend_tx_len; uint8_t rtx_flag; sem_t rtx_sem; diff --git a/src/protocol/libicp67/inc/general_method.h b/src/protocol/libicp67/inc/general_method.h deleted file mode 100644 index 9a811a6..0000000 --- a/src/protocol/libicp67/inc/general_method.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include "myIcp67.h" - - - - -stru_genneral_method* icp67_get_genneral_method(); \ No newline at end of file diff --git a/src/protocol/libicp67/inc/icp67.h b/src/protocol/libicp67/inc/icp67.h index 7502e05..fbf84c9 100644 --- a/src/protocol/libicp67/inc/icp67.h +++ b/src/protocol/libicp67/inc/icp67.h @@ -87,6 +87,13 @@ typedef enum // 帧尾定义 #define ICP67_TAIL (0x16) // 帧尾字符 +// 帧结构常量 +#define ICP67_HEAD_OVERHEAD 4 // head1(1)+len(2)+head2(1) +#define ICP67_FRAME_OVERHEAD 6 // head_overhead(4)+crc(1)+tail(1) +#define ICP67_UPGRADE_TYPE 1 // 升级类型 +#define ICP67_NAME_MAX 256 // 文件名最大长度 +#define ICP67_TM_STRUCT_LEN 7 // 时间结构体长度 + @@ -95,7 +102,7 @@ typedef enum #pragma pack(1) typedef struct { - uint8_t md5[16]; // MD5校验码 + uint8_t md5[ICP67_MD5_LEN]; // MD5校验码 uint16_t num; // 参数个数 uint8_t data[0]; // 参数数据 }stru_ti_1_2; @@ -297,7 +304,7 @@ typedef struct uint32_t id; // 文件ID uint32_t offset; // 偏移地址 uint8_t result; // 结果 - uint8_t md5[16]; // MD5校验码 + uint8_t md5[ICP67_MD5_LEN]; // MD5校验码 uint8_t data[0]; // 数据 }stru_ti_11_10; #pragma pack() @@ -311,7 +318,7 @@ typedef struct uint8_t cmd; // 文件操作 uint32_t id; // 文件ID uint8_t result; // 结果 - uint8_t md5[16]; // MD5校验码 + uint8_t md5[ICP67_MD5_LEN]; // MD5校验码 uint8_t data[0]; // 数据 }stru_ti_11_11; #pragma pack() diff --git a/src/protocol/libicp67/src/general_method.cpp b/src/protocol/libicp67/src/general_method.cpp index 24956dc..d75c8ba 100644 --- a/src/protocol/libicp67/src/general_method.cpp +++ b/src/protocol/libicp67/src/general_method.cpp @@ -1,573 +1,88 @@ -#include "general_method.h" #include "icp67.h" -#include "myLog.h" -#include -LOCAL void icp67_ao_get(stru_icp67 *p_icp67, stru_ti_1_2_data *p_data, uint16_t num); -LOCAL void icp67_ao_set(stru_icp67 *p_icp67, uint8_t *p_data, uint16_t num); -LOCAL void icp67_iec_point_tbl_get(stru_icp67 *p_icp67, uint16_t info_addr); -LOCAL void icp67_time_set(stru_icp67 *p_icp67, stru_ti_5 *p_data); -LOCAL void icp67_self_check_get(stru_icp67 *p_icp67); -LOCAL void icp67_upgrade_start(stru_icp67 *p_icp67, uint8_t dst); -LOCAL void icp67_dir_read(stru_icp67 *p_icp67, uint8_t *p_dir, uint8_t len, uint8_t *tm_start, uint8_t *tm_end); -LOCAL void icp67_file_read_act(stru_icp67 *p_icp67, uint8_t *p_name, uint8_t len); -LOCAL void icp67_file_read_confirm(stru_icp67 *p_icp67, uint8_t result, uint32_t id, uint32_t offset); -LOCAL void icp67_file_write_act(stru_icp67 *p_icp67, uint8_t *p_name, uint8_t len, uint32_t id, uint32_t size, uint16_t crc); -LOCAL void icp67_file_write(stru_icp67 *p_icp67, uint32_t id, uint32_t offset, uint8_t follow, uint8_t *p_data, uint16_t len); -LOCAL void icp67_file_write_end_confirm(stru_icp67 *p_icp67, uint8_t result, uint32_t id, uint8_t *md5); - -LOCAL stru_genneral_method g_genneral_method = +void icp67_set_ao_pop_out_cb(stru_icp67 *p_icp67, icp67_ao_pop_out_cb cb) { - .ao_get_cb = icp67_ao_get, - .ao_pop_out_cb = NULL, - .ao_set_cb = icp67_ao_set, - .iec_point_tbl_get_cb = icp67_iec_point_tbl_get, - .iec_point_tbl_pop_out_cb = NULL, - .time_set_cb = icp67_time_set, - .self_check_get_cb = icp67_self_check_get, - .self_check_pop_out_cb = NULL, - .upgrade_start_cb = icp67_upgrade_start, - - .dir_read_cb = icp67_dir_read, - .dir_pop_out_cb = NULL, - .file_read_act_cb = icp67_file_read_act, - .file_read_act_confirm_cb = NULL, - .file_read_cb = NULL, - .file_read_confirm_cb = icp67_file_read_confirm, - .file_write_act_cb = icp67_file_write_act, - .file_write_act_confirm_cb = NULL, - .file_write_cb = icp67_file_write, - .file_write_confirm_cb = NULL, - .file_write_end_cb = NULL, - .file_write_end_confirm_cb = icp67_file_write_end_confirm, - - .zip_dir_pop_out_cb = NULL, - .zip_file_pop_out_cb = NULL, - - .mx_trans_cb = NULL, - .st_trans_cb = NULL, - .dd_trans_cb = NULL, - .soe_trans_cb = NULL, - .fault_trans_cb = NULL, - .mx_change_cb = NULL -}; - -stru_genneral_method* icp67_get_genneral_method() -{ - return &g_genneral_method; + p_icp67->method.ao_pop_out_cb = cb; } -void icp67_set_ao_get_cb(icp67_ao_get_cb *p_cb) +void icp67_set_iec_point_tbl_pop_out_cb(stru_icp67 *p_icp67, icp67_iec_point_tbl_pop_out_cb cb) { - (*p_cb) = g_genneral_method.ao_get_cb; + p_icp67->method.iec_point_tbl_pop_out_cb = cb; } -void icp67_set_ao_pop_out_cb(icp67_ao_pop_out_cb cb) +void icp67_set_self_check_pop_out_cb(stru_icp67 *p_icp67, icp67_self_check_pop_out_cb cb) { - g_genneral_method.ao_pop_out_cb = cb; + p_icp67->method.self_check_pop_out_cb = cb; } -void icp67_set_ao_set_cb(icp67_ao_set_cb *p_cb) +void icp67_set_dir_pop_out_cb(stru_icp67 *p_icp67, icp67_dir_pop_out_cb cb) { - (*p_cb) = g_genneral_method.ao_set_cb; + p_icp67->method.dir_pop_out_cb = cb; } -void icp67_set_iec_point_tbl_get_cb(icp67_iec_point_tbl_get_cb *p_cb) +void icp67_set_file_read_act_confirm_cb(stru_icp67 *p_icp67, icp67_file_read_act_confirm_cb cb) { - (*p_cb) = g_genneral_method.iec_point_tbl_get_cb; + p_icp67->method.file_read_act_confirm_cb = cb; } -void icp67_set_iec_point_tbl_pop_out_cb(icp67_iec_point_tbl_pop_out_cb cb) +void icp67_set_file_read_cb(stru_icp67 *p_icp67, icp67_file_read_cb cb) { - g_genneral_method.iec_point_tbl_pop_out_cb = cb; + p_icp67->method.file_read_cb = cb; } -void icp67_set_time_set_cb(icp67_time_set_cb *p_cb) +void icp67_set_file_write_act_confirm_cb(stru_icp67 *p_icp67, icp67_file_write_act_confirm_cb cb) { - (*p_cb) = g_genneral_method.time_set_cb; + p_icp67->method.file_write_act_confirm_cb = cb; } -void icp67_set_self_check_get_cb(icp67_self_check_get_cb *p_cb) +void icp67_set_file_write_confirm_cb(stru_icp67 *p_icp67, icp67_file_write_confirm_cb cb) { - (*p_cb) = g_genneral_method.self_check_get_cb; + p_icp67->method.file_write_confirm_cb = cb; } -void icp67_set_self_check_pop_out_cb(icp67_self_check_pop_out_cb cb) +void icp67_set_file_write_end_cb(stru_icp67 *p_icp67, icp67_file_write_end_cb cb) { - g_genneral_method.self_check_pop_out_cb = cb; + p_icp67->method.file_write_end_cb = cb; } -void icp67_set_upgrade_start_cb(icp67_upgrade_start_cb *p_cb) +void icp67_set_zip_dir_pop_out_cb(stru_icp67 *p_icp67, icp67_zip_dir_pop_out_cb cb) { - (*p_cb) = g_genneral_method.upgrade_start_cb; + p_icp67->method.zip_dir_pop_out_cb = cb; } -void icp67_set_dir_read_cb(icp67_dir_read_cb *p_cb) +void icp67_set_zip_file_pop_out_cb(stru_icp67 *p_icp67, icp67_zip_file_pop_out_cb cb) { - (*p_cb) = g_genneral_method.dir_read_cb; + p_icp67->method.zip_file_pop_out_cb = cb; } -void icp67_set_dir_pop_out_cb(icp67_dir_pop_out_cb cb) +void icp67_set_mx_trans_cb(stru_icp67 *p_icp67, icp67_mx_trans_cb cb) { - g_genneral_method.dir_pop_out_cb = cb; + p_icp67->method.mx_trans_cb = cb; } -void icp67_set_file_read_act_cb(icp67_file_read_act_cb *p_cb) +void icp67_set_st_trans_cb(stru_icp67 *p_icp67, icp67_st_trans_cb cb) { - (*p_cb) = g_genneral_method.file_read_act_cb; + p_icp67->method.st_trans_cb = cb; } -void icp67_set_file_read_act_confirm_cb(icp67_file_read_act_confirm_cb cb) +void icp67_set_dd_trans_cb(stru_icp67 *p_icp67, icp67_dd_trans_cb cb) { - g_genneral_method.file_read_act_confirm_cb = cb; + p_icp67->method.dd_trans_cb = cb; } -void icp67_set_file_read_cb(icp67_file_read_cb cb) +void icp67_set_soe_trans_cb(stru_icp67 *p_icp67, icp67_soe_trans_cb cb) { - g_genneral_method.file_read_cb = cb; + p_icp67->method.soe_trans_cb = cb; } -void icp67_set_file_read_confirm_cb(icp67_file_read_confirm_cb *p_cb) +void icp67_set_fault_trans_cb(stru_icp67 *p_icp67, icp67_fault_trans_cb cb) { - (*p_cb) = g_genneral_method.file_read_confirm_cb; + p_icp67->method.fault_trans_cb = cb; } -void icp67_set_file_write_act_cb(icp67_file_write_act_cb *p_cb) +void icp67_set_mx_change_cb(stru_icp67 *p_icp67, icp67_mx_change_cb cb) { - (*p_cb) = g_genneral_method.file_write_act_cb; + p_icp67->method.mx_change_cb = cb; } - -void icp67_set_file_write_act_confirm_cb(icp67_file_write_act_confirm_cb cb) -{ - g_genneral_method.file_write_act_confirm_cb = cb; -} - -void icp67_set_file_write_cb(icp67_file_write_cb *p_cb) -{ - (*p_cb) = g_genneral_method.file_write_cb; -} - -void icp67_set_file_write_confirm_cb(icp67_file_write_confirm_cb cb) -{ - g_genneral_method.file_write_confirm_cb = cb; -} - -void icp67_set_file_write_end_cb(icp67_file_write_end_cb cb) -{ - g_genneral_method.file_write_end_cb = cb; -} - -void icp67_set_file_write_end_confirm_cb(icp67_file_write_end_confirm_cb *p_cb) -{ - (*p_cb) = g_genneral_method.file_write_end_confirm_cb; -} - -void icp67_set_zip_dir_pop_out_cb(icp67_zip_dir_pop_out_cb cb) -{ - g_genneral_method.zip_dir_pop_out_cb = cb; -} - -void icp67_set_zip_file_pop_out_cb(icp67_zip_file_pop_out_cb cb) -{ - g_genneral_method.zip_file_pop_out_cb = cb; -} - -void icp67_set_mx_trans_cb(icp67_mx_trans_cb cb) -{ - g_genneral_method.mx_trans_cb = cb; -} - -void icp67_set_st_trans_cb(icp67_st_trans_cb cb) -{ - g_genneral_method.st_trans_cb = cb; -} - -void icp67_set_dd_trans_cb(icp67_dd_trans_cb cb) -{ - g_genneral_method.dd_trans_cb = cb; -} - -void icp67_set_soe_trans_cb(icp67_soe_trans_cb cb) -{ - g_genneral_method.soe_trans_cb = cb; -} - -void icp67_set_fault_trans_cb(icp67_fault_trans_cb cb) -{ - g_genneral_method.fault_trans_cb = cb; -} - -void icp67_set_mx_change_cb(icp67_mx_change_cb cb) -{ - g_genneral_method.mx_change_cb = cb; -} - - - -LOCAL void icp67_ao_get(stru_icp67 *p_icp67, stru_ti_1_2_data *p_data, uint16_t num) -{ - if(NULL == p_icp67 || NULL == p_data || num == 0) - { - LOG_E("icp67_ao_get: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - icp67_make_head(ENUM_DEV_TYPE_SYS, TI_1, COT_5, TI_1_INFO_ADDR, p_tx, tx_len); - - stru_ti_1_2 *p_asdu = (stru_ti_1_2 *)&p_tx[tx_len]; - memcpy(p_asdu->md5, p_icp67->md5, 16); - p_asdu->num = num; - tx_len += sizeof(stru_ti_1_2); - - for(uint16_t i = 0; i < num; i++) - { - stru_ti_1_2_data *p = (stru_ti_1_2_data *)&p_tx[tx_len]; - memcpy(p, &p_data[i], sizeof(stru_ti_1_2_data)); - tx_len += sizeof(stru_ti_1_2_data); - } - - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); - -} - -LOCAL void icp67_ao_set(stru_icp67 *p_icp67, uint8_t *p_data, uint16_t num) -{ - if(NULL == p_icp67 || NULL == p_data || num == 0) - { - LOG_E("icp67_ao_set: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - icp67_make_head(ENUM_DEV_TYPE_SYS, TI_2, COT_6, TI_1_INFO_ADDR, p_tx, tx_len); - - stru_ti_1_2 *p_asdu = (stru_ti_1_2 *)&p_tx[tx_len]; - memcpy(p_asdu->md5, p_icp67->md5, 16); - p_asdu->num = num; - tx_len += sizeof(stru_ti_1_2); - - uint16_t pos = 0; - - for(uint16_t i = 0; i < num; i++) - { - stru_ti_1_2_data *p_src = (stru_ti_1_2_data *)&p_data[pos]; - memcpy(&p_tx[tx_len], p_src, sizeof(stru_ti_1_2_data_info) + p_src->data_len); - tx_len += (sizeof(stru_ti_1_2_data_info) + p_src->data_len); - pos += (sizeof(stru_ti_1_2_data) + p_src->data_len); - } - - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); - // icp67_reset_tm_cnt(p_icp67); -} - -LOCAL void icp67_iec_point_tbl_get(stru_icp67 *p_icp67, uint16_t info_addr) -{ - if(NULL == p_icp67) - { - LOG_E("icp67_iec_point_tbl_get: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - icp67_make_head(ENUM_DEV_TYPE_SYS, TI_3, COT_5, info_addr, p_tx, tx_len); - - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); -} - -LOCAL void icp67_time_set(stru_icp67 *p_icp67, stru_ti_5 *p_data) -{ - if(NULL == p_icp67 || NULL == p_data) - { - LOG_E("icp67_time_set: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - icp67_make_head(ENUM_DEV_TYPE_SYS, TI_5, COT_5, TI_5_INFO_ADDR, p_tx, tx_len); - - stru_ti_5 *p_asdu = (stru_ti_5 *)&p_tx[tx_len]; - memcpy(p_asdu, p_data, sizeof(stru_ti_5)); - tx_len += sizeof(stru_ti_5); - - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); -} - -LOCAL void icp67_self_check_get(stru_icp67 *p_icp67) -{ - if(NULL == p_icp67) - { - LOG_E("icp67_self_check_get: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - icp67_make_head(ENUM_DEV_TYPE_SYS, TI_6, COT_5, TI_6_INFO_ADDR, p_tx, tx_len); - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); -} - -LOCAL void icp67_upgrade_start(stru_icp67 *p_icp67, uint8_t dst) -{ - if(NULL == p_icp67) - { - LOG_E("icp67_upgrade_start: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - icp67_make_head(dst, TI_9, COT_5, TI_9_INFO_ADDR, p_tx, tx_len); - p_tx[tx_len++] = 0x01; // 升级类型,启动升级 - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); -} - -LOCAL void icp67_dir_read(stru_icp67 *p_icp67, uint8_t *p_dir, uint8_t len, uint8_t *tm_start, uint8_t *tm_end) -{ - if(NULL == p_icp67 || NULL == p_dir || len == 0) - { - LOG_E("icp67_dir_read: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, COT_5, TI_11_INFO_ADDR, p_tx, tx_len); - - stru_ti_11_1 *p_asdu = (stru_ti_11_1 *)&p_tx[tx_len]; - - p_asdu->cmd = FILE_CMD_1; // 读目录 - p_asdu->id = 0; - p_asdu->len = len; - tx_len += sizeof(stru_ti_11_1); - - memcpy(&p_tx[tx_len], p_dir, len); - tx_len += len; - - stru_ti_11_1_info *p_info = (stru_ti_11_1_info *)&p_tx[tx_len]; - if(tm_start && tm_end) - { - p_info->flag = 1; - memcpy(p_info->start_tm, tm_start, 7); - memcpy(p_info->end_tm, tm_end, 7); - } - else - { - p_info->flag = 0; - memset(p_info->start_tm, 0, 7); - memset(p_info->end_tm, 0, 7); - } - tx_len += sizeof(stru_ti_11_1_info); - - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); -} - -LOCAL void icp67_file_read_act(stru_icp67 *p_icp67, uint8_t *p_name, uint8_t len) -{ - if(NULL == p_icp67 || NULL == p_name || len == 0) - { - LOG_E("icp67_file_read_act: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, COT_5, TI_11_INFO_ADDR, p_tx, tx_len); - - stru_ti_11_3 *p_asdu = (stru_ti_11_3 *)&p_tx[tx_len]; - p_asdu->cmd = FILE_CMD_3; // 读文件 - p_asdu->len = len; - tx_len += sizeof(stru_ti_11_3); - - memcpy(&p_tx[tx_len], p_name, len); - tx_len += len; - - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); -} - -LOCAL void icp67_file_read_confirm(stru_icp67 *p_icp67, uint8_t result, uint32_t id, uint32_t offset) -{ - if(NULL == p_icp67) - { - LOG_E("icp67_file_read_confirm: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - uint8_t cot = (result == 0 ? COT_7 : COT_8); // 0:成功,1:失败 - - icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, cot, TI_11_INFO_ADDR, p_tx, tx_len); - - stru_ti_11_6 *p_asdu = (stru_ti_11_6 *)&p_tx[tx_len]; - - p_asdu->cmd = FILE_CMD_6; // 读文件确认 - p_asdu->id = id; - p_asdu->offset = offset; - p_asdu->result = result; - tx_len += sizeof(stru_ti_11_6); - - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); -} - -LOCAL void icp67_file_write_act(stru_icp67 *p_icp67, uint8_t *p_name, uint8_t len, uint32_t id, uint32_t size, uint16_t crc) -{ - if(NULL == p_icp67 || NULL == p_name || len == 0) - { - LOG_E("icp67_file_write_act: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, COT_5, TI_11_INFO_ADDR, p_tx, tx_len); - - stru_ti_11_7 *p_asdu = (stru_ti_11_7 *)&p_tx[tx_len]; - p_asdu->cmd = FILE_CMD_7; // 写文件 - p_asdu->len = len; - tx_len += sizeof(stru_ti_11_7); - - memcpy(&p_tx[tx_len], p_name, len); - tx_len += len; - - stru_ti_11_file_info *p_info = (stru_ti_11_file_info *)&p_tx[tx_len]; - p_info->id = id; - p_info->size = size; - p_info->crc = crc; - tx_len += sizeof(stru_ti_11_file_info); - - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); - - LOG_I("icp67_file_write_act: id=%d, size=%d, crc=%d ,name=%s", id, size, crc, p_name); -} - -LOCAL void icp67_file_write(stru_icp67 *p_icp67, uint32_t id, uint32_t offset, uint8_t follow, uint8_t *p_data, uint16_t len) -{ - if(NULL == p_icp67 || NULL == p_data || len == 0) - { - LOG_E("icp67_file_write: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, COT_5, TI_11_INFO_ADDR, p_tx, tx_len); - - stru_ti_11_9 *p_asdu = (stru_ti_11_9 *)&p_tx[tx_len]; - p_asdu->cmd = FILE_CMD_9; // 写文件 - p_asdu->id = id; - p_asdu->offset = offset; - p_asdu->follow = follow; - p_asdu->len = len; - tx_len += sizeof(stru_ti_11_9); - - memcpy(&p_tx[tx_len], p_data, len); - tx_len += len; - - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); -} - -LOCAL void icp67_file_write_end_confirm(stru_icp67 *p_icp67, uint8_t result, uint32_t id, uint8_t *md5) -{ - if(NULL == p_icp67 || NULL == md5) - { - LOG_E("icp67_file_write_end_confirm: invalid input parameter\n"); - return; - } - - uint8_t *p_tx = p_icp67->tx; - uint16_t tx_len = 0; - - uint8_t cot = (result == 0 ? COT_7 : COT_8); // 0:成功,1:失败 - - icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, cot, TI_11_INFO_ADDR, p_tx, tx_len); - - stru_ti_11_11 *p_asdu = (stru_ti_11_11 *)&p_tx[tx_len]; - p_asdu->cmd = FILE_CMD_11; // 写文件结束确认 - p_asdu->id = id; - p_asdu->result = result; - memcpy(p_asdu->md5, md5, 16); - tx_len += sizeof(stru_ti_11_11); - - icp67_make_tail(p_tx, tx_len); - - p_icp67->tx_len = tx_len; - p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); - - // icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); -} - - - diff --git a/src/protocol/libicp67/src/icp67.cpp b/src/protocol/libicp67/src/icp67.cpp index a38a002..f0bd7fd 100644 --- a/src/protocol/libicp67/src/icp67.cpp +++ b/src/protocol/libicp67/src/icp67.cpp @@ -1,6 +1,5 @@ #include "icp67.h" #include "myLog.h" -#include "general_method.h" #include #include @@ -34,6 +33,19 @@ LOCAL int icp67_decode_ti_11_10(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_ LOCAL int icp67_decode_ti_30_1(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len); LOCAL int icp67_decode_ti_30_3(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len); +LOCAL void icp67_ao_get(stru_icp67 *p_icp67, stru_ti_1_2_data *p_data, uint16_t num); +LOCAL void icp67_ao_set(stru_icp67 *p_icp67, uint8_t *p_data, uint16_t num); +LOCAL void icp67_iec_point_tbl_get(stru_icp67 *p_icp67, uint16_t info_addr); +LOCAL void icp67_time_set(stru_icp67 *p_icp67, stru_ti_5 *p_data); +LOCAL void icp67_self_check_get(stru_icp67 *p_icp67); +LOCAL void icp67_upgrade_start(stru_icp67 *p_icp67, uint8_t dst); +LOCAL void icp67_dir_read(stru_icp67 *p_icp67, uint8_t *p_dir, uint8_t len, uint8_t *tm_start, uint8_t *tm_end); +LOCAL void icp67_file_read_act(stru_icp67 *p_icp67, uint8_t *p_name, uint8_t len); +LOCAL void icp67_file_read_confirm(stru_icp67 *p_icp67, uint8_t result, uint32_t id, uint32_t offset); +LOCAL void icp67_file_write_act(stru_icp67 *p_icp67, uint8_t *p_name, uint8_t len, uint32_t id, uint32_t size, uint16_t crc); +LOCAL void icp67_file_write(stru_icp67 *p_icp67, uint32_t id, uint32_t offset, uint8_t follow, uint8_t *p_data, uint16_t len); +LOCAL void icp67_file_write_end_confirm(stru_icp67 *p_icp67, uint8_t result, uint32_t id, uint8_t *md5); + LOCAL std::map g_map_ti_decode = @@ -88,20 +100,19 @@ LOCAL int icp67_decode_ti_1(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len) return -1; } - if(0 != memcmp(p_icp67->md5, p_asdu->md5, 16)) + if(0 != memcmp(p_icp67->md5, p_asdu->md5, ICP67_MD5_LEN)) { LOG_E("icp67_decode_ti_1 md5 error, md5=%s, p_asdu->md5=%s", p_icp67->md5, p_asdu->md5); return -1; } uint16_t pos = 0; - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - for(uint8_t i = 0; p_genneral_method && p_genneral_method->ao_pop_out_cb && i < p_asdu->num; i++) + for(uint8_t i = 0; p_icp67->method.ao_pop_out_cb && i < p_asdu->num; i++) { stru_ti_1_2_data_info *p_info = (stru_ti_1_2_data_info *)&p_asdu->data[pos]; pos += sizeof(stru_ti_1_2_data_info) + p_info->data_len; - p_genneral_method->ao_pop_out_cb(p_icp67, p_info->data_addr, p_info->data_type, p_info->data_len, p_info->data); + p_icp67->method.ao_pop_out_cb(p_icp67, p_info->data_addr, p_info->data_type, p_info->data_len, p_info->data); } icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0); @@ -157,10 +168,9 @@ LOCAL int icp67_decode_ti_3(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len) LOG_I("ti 3 decode, total %d, frame no %d, follow %d, num %d", p_asdu->total, p_asdu->frame_no, p_asdu->follow, p_asdu->num); - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - if(p_genneral_method && p_genneral_method->iec_point_tbl_pop_out_cb) + if(p_icp67->method.iec_point_tbl_pop_out_cb) { - p_genneral_method->iec_point_tbl_pop_out_cb(p_icp67, p_head->info_addr, p_asdu->num, p_asdu->data); + p_icp67->method.iec_point_tbl_pop_out_cb(p_icp67, p_head->info_addr, p_asdu->num, p_asdu->data); } if(p_asdu->follow) @@ -195,6 +205,8 @@ LOCAL int icp67_decode_ti_3(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len) LOCAL int icp67_decode_ti_4(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len) { + LOG_E("TI_4 not supported"); + icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0); return 0; } @@ -242,15 +254,13 @@ LOCAL int icp67_decode_ti_6(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len) stru_ti_6 *p_asdu = (stru_ti_6 *)p_head->data; - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - uint16_t pos = 0; - for(uint16_t i = 0; p_genneral_method && p_genneral_method->self_check_pop_out_cb && i < p_asdu->st_num; i++) + for(uint16_t i = 0; p_icp67->method.self_check_pop_out_cb && i < p_asdu->st_num; i++) { stru_data_info *p = (stru_data_info *)&p_asdu->st_data[pos]; pos += sizeof(stru_data_info) + p->data_len; - p_genneral_method->self_check_pop_out_cb(p_icp67, p, i); + p_icp67->method.self_check_pop_out_cb(p_icp67, p, i); } icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0); @@ -361,13 +371,11 @@ LOCAL int icp67_decode_ti_200(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_le stru_ti_200_201_202 *p_asdu = (stru_ti_200_201_202 *)p_head->data; - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - uint16_t pos = 0; - for(uint16_t i = 0; p_genneral_method && p_genneral_method->mx_trans_cb && i < p_asdu->num; i++) + for(uint16_t i = 0; p_icp67->method.mx_trans_cb && i < p_asdu->num; i++) { - p_genneral_method->mx_trans_cb(p_icp67, p_asdu->addr+i, *(float *)&p_asdu->data[pos]); - pos += 4; + p_icp67->method.mx_trans_cb(p_icp67, p_asdu->addr+i, *(float *)&p_asdu->data[pos]); + pos += sizeof(float); } return 0; @@ -390,12 +398,10 @@ LOCAL int icp67_decode_ti_201(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_le stru_ti_200_201_202 *p_asdu = (stru_ti_200_201_202 *)p_head->data; - stru_genneral_method *p = icp67_get_genneral_method(); - uint16_t pos = 0; - for(uint16_t i = 0; p && p->st_trans_cb && i < p_asdu->num; i++) + for(uint16_t i = 0; p_icp67->method.st_trans_cb && i < p_asdu->num; i++) { - p->st_trans_cb(p_icp67, p_asdu->addr+i, p_asdu->data[pos++]); + p_icp67->method.st_trans_cb(p_icp67, p_asdu->addr+i, p_asdu->data[pos++]); } return 0; @@ -419,13 +425,11 @@ LOCAL int icp67_decode_ti_202(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_le stru_ti_200_201_202 *p_asdu = (stru_ti_200_201_202 *)p_head->data; - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - uint16_t pos = 0; - for(uint16_t i = 0; p_genneral_method && p_genneral_method->dd_trans_cb && i < p_asdu->num; i++) + for(uint16_t i = 0; p_icp67->method.dd_trans_cb && i < p_asdu->num; i++) { - p_genneral_method->dd_trans_cb(p_icp67, p_asdu->addr+i, *(float *)&p_asdu->data[pos]); - pos += 4; + p_icp67->method.dd_trans_cb(p_icp67, p_asdu->addr+i, *(float *)&p_asdu->data[pos]); + pos += sizeof(float); } return 0; @@ -433,6 +437,8 @@ LOCAL int icp67_decode_ti_202(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_le LOCAL int icp67_decode_ti_203(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len) { + LOG_E("TI_203 not supported"); + icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0); return 0; } @@ -455,14 +461,12 @@ LOCAL int icp67_decode_ti_204(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_le stru_ti_204_205_207 *p_asdu = (stru_ti_204_205_207 *)p_head->data; uint16_t pos = 0; - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - - for(uint16_t i = 0; p_genneral_method && p_genneral_method->soe_trans_cb && i < p_asdu->num; i++) + for(uint16_t i = 0; p_icp67->method.soe_trans_cb && i < p_asdu->num; i++) { stru_st_info *p_st_info = (stru_st_info *)&p_asdu->data[pos]; pos += sizeof(stru_st_info); - p_genneral_method->soe_trans_cb(p_icp67, p_st_info); + p_icp67->method.soe_trans_cb(p_icp67, p_st_info); } return 0; @@ -487,9 +491,6 @@ LOCAL int icp67_decode_ti_205(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_le stru_ti_204_205_207 *p_asdu = (stru_ti_204_205_207 *)p_head->data; uint16_t pos = 0; - - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - std::vector st_info_vec; std::vector mx_info_vec; @@ -520,9 +521,9 @@ LOCAL int icp67_decode_ti_205(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_le fault_info.mx_num = mx_info_vec.size(); fault_info.p_mx_info = mx_info_vec.data(); - if(p_genneral_method && p_genneral_method->fault_trans_cb) + if(p_icp67->method.fault_trans_cb) { - p_genneral_method->fault_trans_cb(p_icp67, p_asdu->num, &fault_info); + p_icp67->method.fault_trans_cb(p_icp67, p_asdu->num, &fault_info); } return 0; @@ -551,14 +552,12 @@ LOCAL int icp67_decode_ti_207(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_le stru_ti_204_205_207 *p_asdu = (stru_ti_204_205_207 *)p_head->data; uint16_t pos = 0; - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - - for(uint16_t i = 0; p_genneral_method && p_genneral_method->mx_change_cb && i < p_asdu->num; i++) + for(uint16_t i = 0; p_icp67->method.mx_change_cb && i < p_asdu->num; i++) { stru_mx_info *p_mx_info = (stru_mx_info *)&p_asdu->data[pos]; pos += sizeof(stru_mx_info); - p_genneral_method->mx_change_cb(p_icp67, p_mx_info); + p_icp67->method.mx_change_cb(p_icp67, p_mx_info); } return 0; @@ -578,30 +577,29 @@ LOCAL int icp67_decode_ti_11_2(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l stru_ti_11_2 *p_asdu = (stru_ti_11_2 *)p_head->data; uint16_t pos = 0; - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); uint8_t len = 0; - uint8_t name[256] = {0}; + uint8_t name[ICP67_NAME_MAX] = {0}; uint32_t attr = 0; uint32_t size = 0; uint8_t follow = 1; - for(uint16_t i = 0; p_genneral_method && p_genneral_method->dir_pop_out_cb && i < p_asdu->num; i++) + for(uint16_t i = 0; p_icp67->method.dir_pop_out_cb && i < p_asdu->num; i++) { len = p_asdu->data[pos++]; memcpy(name, p_asdu->data + pos, len); name[len] = '\0'; pos += len; attr = *(uint32_t *)&p_asdu->data[pos]; - pos += 4; + pos += sizeof(uint32_t); size = *(uint32_t *)&p_asdu->data[pos]; - pos += 4; + pos += sizeof(uint32_t); if(p_asdu->follow == 0 && i == (p_asdu->num - 1)) { follow = 0; } - p_genneral_method->dir_pop_out_cb(p_icp67, name, len, attr, size, follow); + p_icp67->method.dir_pop_out_cb(p_icp67, name, len, attr, size, follow); } icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0); @@ -622,7 +620,7 @@ LOCAL int icp67_decode_ti_11_4(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l stru_ti_11_4 *p_asdu = (stru_ti_11_4 *)p_head->data; uint16_t pos = 0; - uint8_t name[256] = {0}; + uint8_t name[ICP67_NAME_MAX] = {0}; uint32_t id = 0; uint32_t size = 0; uint16_t crc = 0; @@ -631,17 +629,15 @@ LOCAL int icp67_decode_ti_11_4(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l name[p_asdu->len] = '\0'; pos += p_asdu->len; id = *(uint32_t *)&p_asdu->data[pos]; - pos += 4; + pos += sizeof(uint32_t); size = *(uint32_t *)&p_asdu->data[pos]; - pos += 4; + pos += sizeof(uint32_t); crc = *(uint16_t *)&p_asdu->data[pos]; - pos += 2; + pos += sizeof(uint16_t); - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - - if(p_genneral_method && p_genneral_method->file_read_act_confirm_cb) + if(p_icp67->method.file_read_act_confirm_cb) { - p_genneral_method->file_read_act_confirm_cb(p_icp67, name, p_asdu->len, id, size, crc); + p_icp67->method.file_read_act_confirm_cb(p_icp67, name, p_asdu->len, id, size, crc); } icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0); @@ -667,11 +663,9 @@ LOCAL int icp67_decode_ti_11_5(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l return -1; } - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - - if(p_genneral_method && p_genneral_method->file_read_cb) + if(p_icp67->method.file_read_cb) { - p_genneral_method->file_read_cb(p_icp67, p_asdu->id, p_asdu->offset, p_asdu->follow, p_asdu->data, p_asdu->len); + p_icp67->method.file_read_cb(p_icp67, p_asdu->id, p_asdu->offset, p_asdu->follow, p_asdu->data, p_asdu->len); } icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0); @@ -698,23 +692,21 @@ LOCAL int icp67_decode_ti_11_8(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l } uint16_t pos = 0; - uint8_t name[256] = {0}; + uint8_t name[ICP67_NAME_MAX] = {0}; uint32_t id = 0; - uint32_t size = 0; + uint32_t size_tmp = 0; memcpy(name, p_asdu->data, p_asdu->len); name[p_asdu->len] = '\0'; pos += p_asdu->len; id = *(uint32_t *)&p_asdu->data[pos]; - pos += 4; - size = *(uint32_t *)&p_asdu->data[pos]; - pos += 4; + pos += sizeof(uint32_t); + size_tmp = *(uint32_t *)&p_asdu->data[pos]; + pos += sizeof(uint32_t); - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - - if(p_genneral_method && p_genneral_method->file_write_act_confirm_cb) + if(p_icp67->method.file_write_act_confirm_cb) { - p_genneral_method->file_write_act_confirm_cb(p_icp67, p_asdu->result, name, p_asdu->len, id, size); + p_icp67->method.file_write_act_confirm_cb(p_icp67, p_asdu->result, name, p_asdu->len, id, size_tmp); } icp67_rtx_flag_set(p_icp67, ICP67_RX_FLAG, 0, 0); @@ -732,22 +724,18 @@ LOCAL int icp67_decode_ti_11_10(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_ stru_head *p_head = (stru_head *)p_rx; stru_ti_11_10 *p_asdu = (stru_ti_11_10 *)p_head->data; - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - if(FILE_WRITE_CONT_0 == p_asdu->result) { - // LOG_I("ti 11 10: end, result %d, id %d, offset %d", p_asdu->result, p_asdu->id, p_asdu->offset); - if(p_genneral_method && p_genneral_method->file_write_end_cb) + if(p_icp67->method.file_write_end_cb) { - p_genneral_method->file_write_end_cb(p_icp67, p_asdu->result, p_asdu->id, p_asdu->offset, p_asdu->md5); + p_icp67->method.file_write_end_cb(p_icp67, p_asdu->result, p_asdu->id, p_asdu->offset, p_asdu->md5); } } else if(FILE_WRITE_CONT_1 == p_asdu->result) { - // LOG_I("ti 11 10: offset %d", p_asdu->offset); - if(p_genneral_method && p_genneral_method->file_write_confirm_cb) + if(p_icp67->method.file_write_confirm_cb) { - p_genneral_method->file_write_confirm_cb(p_icp67, p_asdu->result, p_asdu->id, p_asdu->offset); + p_icp67->method.file_write_confirm_cb(p_icp67, p_asdu->result, p_asdu->id, p_asdu->offset); } } else @@ -772,7 +760,7 @@ LOCAL int icp67_decode_ti_30_1(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l stru_head *p_head = (stru_head *)p_rx; stru_ti_30_1 *p_asdu = (stru_ti_30_1 *)p_head->data; - uint8_t zip_name[256] = {0}; + uint8_t zip_name[ICP67_NAME_MAX] = {0}; uint16_t pos = 0; memcpy(zip_name, p_asdu->data, p_asdu->len); @@ -793,15 +781,14 @@ LOCAL int icp67_decode_ti_30_1(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l file_info.name[file_info.len] = '\0'; pos += file_info.len; file_info.size = *(uint32_t *)&p_asdu->data[pos]; - pos += 4; + pos += sizeof(uint32_t); zip_file_vec.push_back(file_info); } - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - if(p_genneral_method && p_genneral_method->zip_dir_pop_out_cb) + if(p_icp67->method.zip_dir_pop_out_cb) { - p_genneral_method->zip_dir_pop_out_cb(p_icp67, p_asdu->zip_type, zip_name, p_asdu->len, file_num, zip_file_vec.data()); + p_icp67->method.zip_dir_pop_out_cb(p_icp67, p_asdu->zip_type, zip_name, p_asdu->len, file_num, zip_file_vec.data()); } return 0; @@ -819,11 +806,9 @@ LOCAL int icp67_decode_ti_30_3(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_l stru_ti_30_3 *p_asdu = (stru_ti_30_3 *)p_head->data; - stru_genneral_method *p_genneral_method = icp67_get_genneral_method(); - - if(p_genneral_method && p_genneral_method->zip_file_pop_out_cb) + if(p_icp67->method.zip_file_pop_out_cb) { - p_genneral_method->zip_file_pop_out_cb(p_icp67, p_asdu->file_no, p_asdu->offset, p_asdu->data, p_asdu->len); + p_icp67->method.zip_file_pop_out_cb(p_icp67, p_asdu->file_no, p_asdu->offset, p_asdu->data, p_asdu->len); } return 0; @@ -862,8 +847,8 @@ void icp67_make_head(uint8_t dst, uint8_t ti, uint8_t cot, uint16_t inf, uint8_t void icp67_make_tail(uint8_t *p_tx, uint16_t &tx_len) { stru_head *p_head = (stru_head *)p_tx; - p_head->len = tx_len - 4; // head1, len, head2, - p_tx[tx_len ++] = crc_check_sum(p_tx + 4, p_head->len); + p_head->len = tx_len - ICP67_HEAD_OVERHEAD; + p_tx[tx_len ++] = crc_check_sum(p_tx + ICP67_HEAD_OVERHEAD, p_head->len); p_tx[tx_len ++] = ICP67_TAIL; } @@ -878,7 +863,7 @@ LOCAL int icp67_search_frame(uint8_t *p_data, uint16_t len, uint16_t *p_pos, uin { stru_head *p_head = (stru_head *)(p_data + i); - if(i +2 + sizeof(stru_head) > len) + if(i + sizeof(uint16_t) + sizeof(stru_head) > len) { break; } @@ -888,23 +873,23 @@ LOCAL int icp67_search_frame(uint8_t *p_data, uint16_t len, uint16_t *p_pos, uin continue; } - if((p_head->len + 6) > (len - i)) + if((p_head->len + ICP67_FRAME_OVERHEAD) > (len - i)) { break; } - if(p_data[i + p_head->len + 4] != crc_check_sum(p_data + i + 4, p_head->len)) + if(p_data[i + p_head->len + ICP67_HEAD_OVERHEAD] != crc_check_sum(p_data + i + ICP67_HEAD_OVERHEAD, p_head->len)) { continue; } - if(p_data[i + p_head->len + 5] != ICP67_TAIL) + if(p_data[i + p_head->len + ICP67_HEAD_OVERHEAD + 1] != ICP67_TAIL) { continue; } (*p_pos) = i; - (*p_valid_len) = p_head->len + 6; + (*p_valid_len) = p_head->len + ICP67_FRAME_OVERHEAD; return 0; } @@ -941,11 +926,6 @@ LOCAL int icp67_decode(stru_icp67 *p_icp67, uint8_t *p_rx, uint16_t rx_len) stru_head *p_head = (stru_head *)p_rx; - // if(p_head->ti != TI_200 && p_head->ti != TI_201) - // { - // icp67_show_frame(p_rx, rx_len); - // } - if(g_map_ti_decode.find(p_head->ti) == g_map_ti_decode.end()) { LOG_E("not support ti %d\n", p_head->ti); @@ -964,6 +944,10 @@ LOCAL void icp67_timer_handler(stru_icp67 *p_icp67) return; } + sem_wait(&p_icp67->rtx_sem); + p_icp67->tm_cnt++; + sem_post(&p_icp67->rtx_sem); + uint8_t rtx_flag = 0; uint8_t resend_cnt = 0; uint32_t tm_cnt = 0; @@ -972,14 +956,15 @@ LOCAL void icp67_timer_handler(stru_icp67 *p_icp67) if(rtx_flag == ICP67_TX_FLAG && resend_cnt < ICP67_RESEND_MAX && tm_cnt >= p_icp67->tm_out) { p_icp67->send_cb(p_icp67->resend_tx, p_icp67->resend_tx_len, p_icp67->arg); - p_icp67->resend_cnt ++; + + sem_wait(&p_icp67->rtx_sem); + p_icp67->resend_cnt++; p_icp67->tm_cnt = 0; + sem_post(&p_icp67->rtx_sem); LOG_I("resend cnt %d", p_icp67->resend_cnt); icp67_show_frame(p_icp67->resend_tx, p_icp67->resend_tx_len); } - - p_icp67->tm_cnt++; } void icp67_init(stru_icp67 *p_icp67, icp67_send_cb send_cb, void *arg) @@ -995,8 +980,41 @@ void icp67_init(stru_icp67 *p_icp67, icp67_send_cb send_cb, void *arg) sem_init(&p_icp67->rtx_sem, 0, 1); p_icp67->resend_cnt = 0; - p_icp67->tm_out = 1000 / 10; // 1000ms + p_icp67->tm_out = ICP67_TM_OUT_MS / ICP67_TM_TICK_MS; p_icp67->tm_cnt = 0; + + p_icp67->method.ao_get_cb = icp67_ao_get; + p_icp67->method.ao_pop_out_cb = NULL; + p_icp67->method.ao_set_cb = icp67_ao_set; + p_icp67->method.iec_point_tbl_get_cb = icp67_iec_point_tbl_get; + p_icp67->method.iec_point_tbl_pop_out_cb = NULL; + p_icp67->method.time_set_cb = icp67_time_set; + p_icp67->method.self_check_get_cb = icp67_self_check_get; + p_icp67->method.self_check_pop_out_cb = NULL; + p_icp67->method.upgrade_start_cb = icp67_upgrade_start; + + p_icp67->method.dir_read_cb = icp67_dir_read; + p_icp67->method.dir_pop_out_cb = NULL; + p_icp67->method.file_read_act_cb = icp67_file_read_act; + p_icp67->method.file_read_act_confirm_cb = NULL; + p_icp67->method.file_read_cb = NULL; + p_icp67->method.file_read_confirm_cb = icp67_file_read_confirm; + p_icp67->method.file_write_act_cb = icp67_file_write_act; + p_icp67->method.file_write_act_confirm_cb = NULL; + p_icp67->method.file_write_cb = icp67_file_write; + p_icp67->method.file_write_confirm_cb = NULL; + p_icp67->method.file_write_end_cb = NULL; + p_icp67->method.file_write_end_confirm_cb = icp67_file_write_end_confirm; + + p_icp67->method.zip_dir_pop_out_cb = NULL; + p_icp67->method.zip_file_pop_out_cb = NULL; + + p_icp67->method.mx_trans_cb = NULL; + p_icp67->method.st_trans_cb = NULL; + p_icp67->method.dd_trans_cb = NULL; + p_icp67->method.soe_trans_cb = NULL; + p_icp67->method.fault_trans_cb = NULL; + p_icp67->method.mx_change_cb = NULL; } int icp67_set_ao_cfg_md5(stru_icp67 *p_icp67, uint8_t *p_md5) @@ -1006,7 +1024,7 @@ int icp67_set_ao_cfg_md5(stru_icp67 *p_icp67, uint8_t *p_md5) return -1; } - memcpy(p_icp67->md5, p_md5, 16); + memcpy(p_icp67->md5, p_md5, ICP67_MD5_LEN); return 0; } @@ -1024,6 +1042,10 @@ void icp67_rtx_flag_get(stru_icp67 *p_icp67, uint8_t &flag, uint8_t &resend_cnt, void icp67_rtx_flag_set(stru_icp67 *p_icp67, uint8_t flag, uint8_t resend_cnt, uint32_t tm_cnt) { sem_wait(&p_icp67->rtx_sem); + if(flag == ICP67_TX_FLAG && p_icp67->rtx_flag == ICP67_TX_FLAG) + { + LOG_E("icp67_rtx_flag_set: overriding pending TX, prev resend_cnt=%d", p_icp67->resend_cnt); + } p_icp67->rtx_flag = flag; p_icp67->resend_cnt = resend_cnt; p_icp67->tm_cnt = tm_cnt; @@ -1044,4 +1066,365 @@ void icp67_reset_resend_cnt(stru_icp67 *p_icp67) void icp67_reset_tm_cnt(stru_icp67 *p_icp67) { p_icp67->tm_cnt = 0; +} + + +LOCAL void icp67_ao_get(stru_icp67 *p_icp67, stru_ti_1_2_data *p_data, uint16_t num) +{ + if(NULL == p_icp67 || NULL == p_data || num == 0) + { + LOG_E("icp67_ao_get: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + icp67_make_head(ENUM_DEV_TYPE_SYS, TI_1, COT_5, TI_1_INFO_ADDR, p_tx, tx_len); + + stru_ti_1_2 *p_asdu = (stru_ti_1_2 *)&p_tx[tx_len]; + memcpy(p_asdu->md5, p_icp67->md5, ICP67_MD5_LEN); + p_asdu->num = num; + tx_len += sizeof(stru_ti_1_2); + + for(uint16_t i = 0; i < num; i++) + { + stru_ti_1_2_data *p = (stru_ti_1_2_data *)&p_tx[tx_len]; + memcpy(p, &p_data[i], sizeof(stru_ti_1_2_data)); + tx_len += sizeof(stru_ti_1_2_data); + } + + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); + + icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); + +} + +LOCAL void icp67_ao_set(stru_icp67 *p_icp67, uint8_t *p_data, uint16_t num) +{ + if(NULL == p_icp67 || NULL == p_data || num == 0) + { + LOG_E("icp67_ao_set: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + icp67_make_head(ENUM_DEV_TYPE_SYS, TI_2, COT_6, TI_1_INFO_ADDR, p_tx, tx_len); + + stru_ti_1_2 *p_asdu = (stru_ti_1_2 *)&p_tx[tx_len]; + memcpy(p_asdu->md5, p_icp67->md5, ICP67_MD5_LEN); + p_asdu->num = num; + tx_len += sizeof(stru_ti_1_2); + + uint16_t pos = 0; + + for(uint16_t i = 0; i < num; i++) + { + stru_ti_1_2_data *p_src = (stru_ti_1_2_data *)&p_data[pos]; + memcpy(&p_tx[tx_len], p_src, sizeof(stru_ti_1_2_data_info) + p_src->data_len); + tx_len += (sizeof(stru_ti_1_2_data_info) + p_src->data_len); + pos += (sizeof(stru_ti_1_2_data) + p_src->data_len); + } + + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); + + icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); +} + +LOCAL void icp67_iec_point_tbl_get(stru_icp67 *p_icp67, uint16_t info_addr) +{ + if(NULL == p_icp67) + { + LOG_E("icp67_iec_point_tbl_get: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + icp67_make_head(ENUM_DEV_TYPE_SYS, TI_3, COT_5, info_addr, p_tx, tx_len); + + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); + + icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); +} + +LOCAL void icp67_time_set(stru_icp67 *p_icp67, stru_ti_5 *p_data) +{ + if(NULL == p_icp67 || NULL == p_data) + { + LOG_E("icp67_time_set: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + icp67_make_head(ENUM_DEV_TYPE_SYS, TI_5, COT_5, TI_5_INFO_ADDR, p_tx, tx_len); + + stru_ti_5 *p_asdu = (stru_ti_5 *)&p_tx[tx_len]; + memcpy(p_asdu, p_data, sizeof(stru_ti_5)); + tx_len += sizeof(stru_ti_5); + + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); + + icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); +} + +LOCAL void icp67_self_check_get(stru_icp67 *p_icp67) +{ + if(NULL == p_icp67) + { + LOG_E("icp67_self_check_get: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + icp67_make_head(ENUM_DEV_TYPE_SYS, TI_6, COT_5, TI_6_INFO_ADDR, p_tx, tx_len); + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); + + icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); +} + +LOCAL void icp67_upgrade_start(stru_icp67 *p_icp67, uint8_t dst) +{ + if(NULL == p_icp67) + { + LOG_E("icp67_upgrade_start: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + icp67_make_head(dst, TI_9, COT_5, TI_9_INFO_ADDR, p_tx, tx_len); + p_tx[tx_len++] = ICP67_UPGRADE_TYPE; + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); + + icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); +} + +LOCAL void icp67_dir_read(stru_icp67 *p_icp67, uint8_t *p_dir, uint8_t len, uint8_t *tm_start, uint8_t *tm_end) +{ + if(NULL == p_icp67 || NULL == p_dir || len == 0) + { + LOG_E("icp67_dir_read: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, COT_5, TI_11_INFO_ADDR, p_tx, tx_len); + + stru_ti_11_1 *p_asdu = (stru_ti_11_1 *)&p_tx[tx_len]; + + p_asdu->cmd = FILE_CMD_1; + p_asdu->id = 0; + p_asdu->len = len; + tx_len += sizeof(stru_ti_11_1); + + memcpy(&p_tx[tx_len], p_dir, len); + tx_len += len; + + stru_ti_11_1_info *p_info = (stru_ti_11_1_info *)&p_tx[tx_len]; + if(tm_start && tm_end) + { + p_info->flag = 1; + memcpy(p_info->start_tm, tm_start, ICP67_TM_STRUCT_LEN); + memcpy(p_info->end_tm, tm_end, ICP67_TM_STRUCT_LEN); + } + else + { + p_info->flag = 0; + memset(p_info->start_tm, 0, ICP67_TM_STRUCT_LEN); + memset(p_info->end_tm, 0, ICP67_TM_STRUCT_LEN); + } + tx_len += sizeof(stru_ti_11_1_info); + + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); + + icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); +} + +LOCAL void icp67_file_read_act(stru_icp67 *p_icp67, uint8_t *p_name, uint8_t len) +{ + if(NULL == p_icp67 || NULL == p_name || len == 0) + { + LOG_E("icp67_file_read_act: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, COT_5, TI_11_INFO_ADDR, p_tx, tx_len); + + stru_ti_11_3 *p_asdu = (stru_ti_11_3 *)&p_tx[tx_len]; + p_asdu->cmd = FILE_CMD_3; + p_asdu->len = len; + tx_len += sizeof(stru_ti_11_3); + + memcpy(&p_tx[tx_len], p_name, len); + tx_len += len; + + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); + + icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); +} + +LOCAL void icp67_file_read_confirm(stru_icp67 *p_icp67, uint8_t result, uint32_t id, uint32_t offset) +{ + if(NULL == p_icp67) + { + LOG_E("icp67_file_read_confirm: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + uint8_t cot = (result == 0 ? COT_7 : COT_8); + + icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, cot, TI_11_INFO_ADDR, p_tx, tx_len); + + stru_ti_11_6 *p_asdu = (stru_ti_11_6 *)&p_tx[tx_len]; + + p_asdu->cmd = FILE_CMD_6; + p_asdu->id = id; + p_asdu->offset = offset; + p_asdu->result = result; + tx_len += sizeof(stru_ti_11_6); + + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); + + icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); +} + +LOCAL void icp67_file_write_act(stru_icp67 *p_icp67, uint8_t *p_name, uint8_t len, uint32_t id, uint32_t size, uint16_t crc) +{ + if(NULL == p_icp67 || NULL == p_name || len == 0) + { + LOG_E("icp67_file_write_act: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, COT_5, TI_11_INFO_ADDR, p_tx, tx_len); + + stru_ti_11_7 *p_asdu = (stru_ti_11_7 *)&p_tx[tx_len]; + p_asdu->cmd = FILE_CMD_7; + p_asdu->len = len; + tx_len += sizeof(stru_ti_11_7); + + memcpy(&p_tx[tx_len], p_name, len); + tx_len += len; + + stru_ti_11_file_info *p_info = (stru_ti_11_file_info *)&p_tx[tx_len]; + p_info->id = id; + p_info->size = size; + p_info->crc = crc; + tx_len += sizeof(stru_ti_11_file_info); + + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); + + icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); + + LOG_I("icp67_file_write_act: id=%d, size=%d, crc=%d ,name=%s", id, size, crc, p_name); +} + +LOCAL void icp67_file_write(stru_icp67 *p_icp67, uint32_t id, uint32_t offset, uint8_t follow, uint8_t *p_data, uint16_t len) +{ + if(NULL == p_icp67 || NULL == p_data || len == 0) + { + LOG_E("icp67_file_write: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, COT_5, TI_11_INFO_ADDR, p_tx, tx_len); + + stru_ti_11_9 *p_asdu = (stru_ti_11_9 *)&p_tx[tx_len]; + p_asdu->cmd = FILE_CMD_9; + p_asdu->id = id; + p_asdu->offset = offset; + p_asdu->follow = follow; + p_asdu->len = len; + tx_len += sizeof(stru_ti_11_9); + + memcpy(&p_tx[tx_len], p_data, len); + tx_len += len; + + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); + + icp67_rtx_flag_set(p_icp67, ICP67_TX_FLAG, 0, 0); +} + +LOCAL void icp67_file_write_end_confirm(stru_icp67 *p_icp67, uint8_t result, uint32_t id, uint8_t *md5) +{ + if(NULL == p_icp67 || NULL == md5) + { + LOG_E("icp67_file_write_end_confirm: invalid input parameter\n"); + return; + } + + uint8_t *p_tx = p_icp67->tx; + uint16_t tx_len = 0; + + uint8_t cot = (result == 0 ? COT_7 : COT_8); + + icp67_make_head(ENUM_DEV_TYPE_SYS, TI_11, cot, TI_11_INFO_ADDR, p_tx, tx_len); + + stru_ti_11_11 *p_asdu = (stru_ti_11_11 *)&p_tx[tx_len]; + p_asdu->cmd = FILE_CMD_11; + p_asdu->id = id; + p_asdu->result = result; + memcpy(p_asdu->md5, md5, ICP67_MD5_LEN); + tx_len += sizeof(stru_ti_11_11); + + icp67_make_tail(p_tx, tx_len); + + p_icp67->tx_len = tx_len; + p_icp67->send_cb(p_tx, tx_len, p_icp67->arg); } \ No newline at end of file diff --git a/src/system/libcom_decode/src/decode_frame_codec.cpp b/src/system/libcom_decode/src/decode_frame_codec.cpp index c8d9d9a..cca9746 100644 --- a/src/system/libcom_decode/src/decode_frame_codec.cpp +++ b/src/system/libcom_decode/src/decode_frame_codec.cpp @@ -38,7 +38,7 @@ LOCAL uint8_t crc_check_sum(uint8_t *p_data, uint16_t len) /* * 在数据流中搜索一个完整的 ICP66 帧 - * 帧格式: 0x66 0x66 len(2B) data(lenB) crc(1B) 0x16 + * 帧格式: 0x66 len(2B) 0x66 data(lenB) crc(1B) 0x16 * 对端使用 stru_head 结构体封帧,因此通过 stru_head 字段解析 */ int icp66_search_frame(uint8_t *p_rx, uint16_t rx_len, uint16_t *p_pos, uint16_t *p_len) diff --git a/src/system/libdatacenter/src/dc_signal.cpp b/src/system/libdatacenter/src/dc_signal.cpp index 139ff0a..6c5dfb6 100644 --- a/src/system/libdatacenter/src/dc_signal.cpp +++ b/src/system/libdatacenter/src/dc_signal.cpp @@ -657,6 +657,7 @@ LOCAL int dc_check_ctrl_valid(const stru_signal *p_signal, SIGNAL_CTRL_STEP step } + LOCAL int dc_check_val_valid(const stru_signal *p_signal, uint8_t setting_zone, const void *p_data) { stru_signal_param param = p_signal->param; diff --git a/src/system/libself_ptl/inc/self_ptl.h b/src/system/libself_ptl/inc/self_ptl.h index 5c402c4..74f241d 100644 --- a/src/system/libself_ptl/inc/self_ptl.h +++ b/src/system/libself_ptl/inc/self_ptl.h @@ -6,7 +6,8 @@ #define MODULE_SELF_PTL "self_ptl" -#define IEC_START 0x68 +#define IEC_START_1 0x68 +#define IEC_START_2 0x10 #define IEC_TAIL 0x16 diff --git a/src/system/libself_ptl/src/method.cpp b/src/system/libself_ptl/src/method.cpp index d0dbe8e..745c0df 100644 --- a/src/system/libself_ptl/src/method.cpp +++ b/src/system/libself_ptl/src/method.cpp @@ -21,6 +21,7 @@ + LOCAL std::vector g_dir_info_vec; LOCAL std::string get_base_path() @@ -84,12 +85,12 @@ LOCAL int file_write(const char *file_name, uint32_t offset, uint8_t *p_data, ui LOCAL int file_read(const char *file_name, uint32_t offset, uint8_t *p_data, uint16_t len); LOCAL int file_size_get(const char *file_name, uint32_t *p_size); -LOCAL void test_ao_get(stru_icp67 *p_icp67, stru_genneral_method *p_method); -LOCAL void test_iec_point_tbl_get(stru_icp67 *p_icp67, stru_genneral_method *p_method); -LOCAL void test_time_set(stru_icp67 *p_icp67, stru_genneral_method *p_method); -LOCAL void test_self_check_get(stru_icp67 *p_icp67, stru_genneral_method *p_method); -LOCAL void test_upgrade_start(stru_icp67 *p_icp67, stru_genneral_method *p_method); -LOCAL void test_file(stru_icp67 *p_icp67, stru_genneral_method *p_method); +LOCAL void test_ao_get(stru_icp67 *p_icp67); +LOCAL void test_iec_point_tbl_get(stru_icp67 *p_icp67); +LOCAL void test_time_set(stru_icp67 *p_icp67); +LOCAL void test_self_check_get(stru_icp67 *p_icp67); +LOCAL void test_upgrade_start(stru_icp67 *p_icp67); +LOCAL void test_file(stru_icp67 *p_icp67); @@ -105,7 +106,7 @@ LOCAL std::map g_map_iec_point_tbl_decode = {ST_OPER_INFO_ADDR, iec_point_tbl_decode_st_oper} }; -typedef void (* local_test)(stru_icp67 *p_icp67, stru_genneral_method *p_method); +typedef void (* local_test)(stru_icp67 *p_icp67); LOCAL std::map g_map_local_test = { {1, test_ao_get}, @@ -273,10 +274,9 @@ void file_read(stru_icp67 *p_icp67, uint32_t id, uint32_t offset, uint32_t follo LOG_I("file_read: read file %s success", file_name.c_str()); } - stru_genneral_method *p_method = self_ptl_method_ptr_get(); - if(p_method && p_method->file_read_cb) + if(p_icp67->method.file_read_confirm_cb) { - p_method->file_read_confirm_cb(p_icp67, 0, id, offset+len); + p_icp67->method.file_read_confirm_cb(p_icp67, 0, id, offset+len); } } @@ -313,10 +313,10 @@ void file_write_act_confirm(stru_icp67 *p_icp67, uint8_t result, uint8_t *p_name uint8_t file_data[FILE_TRANS_FRMAE_LEN] = {0}; file_read(file_name.c_str(), 0, file_data, frame_len); - stru_genneral_method *p_method = self_ptl_method_ptr_get(); - if(p_method && p_method->file_write_cb) + stru_icp67 *p_icp67_task = self_ptl_icp67_ptr_get(); + if(p_icp67_task->method.file_write_cb) { - p_method->file_write_cb(p_icp67, 0, 0, follow, file_data, frame_len); + p_icp67_task->method.file_write_cb(p_icp67, 0, 0, follow, file_data, frame_len); } StartMD5(&file_md5_ctx); @@ -352,10 +352,10 @@ void file_write_confirm(stru_icp67 *p_icp67, uint8_t result, uint32_t id, uint32 // LOG_I("ti 11 9: follow %d, frame_len %d, offset %d, size %d", follow, frame_len, offset, size); usleep(5000); - stru_genneral_method *p_method = self_ptl_method_ptr_get(); - if(p_method && p_method->file_write_cb) + stru_icp67 *p_icp67_task = self_ptl_icp67_ptr_get(); + if(p_icp67_task->method.file_write_cb) { - p_method->file_write_cb(p_icp67, id, offset, follow, file_data, frame_len); + p_icp67_task->method.file_write_cb(p_icp67, id, offset, follow, file_data, frame_len); } EncodeMD5(&file_md5_ctx, file_data, frame_len); @@ -383,10 +383,10 @@ void file_write_end(stru_icp67 *p_icp67, uint8_t result, uint32_t id, uint32_t o LOG_I("file_write_end: write file %s success", g_file_name.c_str()); } - stru_genneral_method *p_method = self_ptl_method_ptr_get(); - if(p_method && p_method->file_write_end_confirm_cb) + stru_icp67 *p_icp67_task = self_ptl_icp67_ptr_get(); + if(p_icp67_task->method.file_write_end_confirm_cb) { - p_method->file_write_end_confirm_cb(p_icp67, result, id, file_md5); + p_icp67_task->method.file_write_end_confirm_cb(p_icp67, result, id, file_md5); } } @@ -924,7 +924,7 @@ LOCAL int file_size_get(const char *file_name, uint32_t *p_size) } -LOCAL void test_ao_get(stru_icp67 *p_icp67, stru_genneral_method *p_method) +LOCAL void test_ao_get(stru_icp67 *p_icp67) { stru_self_ptl_cfg_data *p_app_cfg_data = self_ptl_cfg_data_ptr_get(); @@ -967,20 +967,20 @@ LOCAL void test_ao_get(stru_icp67 *p_icp67, stru_genneral_method *p_method) g_local_ao_get.tx_cnt = cnt; LOG_I("ao_get: i %d, cnt %d, tx_cnt %d, offset %d, size %d", i, cnt, g_local_ao_get.tx_cnt, g_local_ao_get.offset, p_app_cfg_data->ao_vec.size()); - p_method->ao_get_cb(p_icp67, data, cnt); + p_icp67->method.ao_get_cb(p_icp67, data, cnt); } -LOCAL void test_iec_point_tbl_get(stru_icp67 *p_icp67, stru_genneral_method *p_method) +LOCAL void test_iec_point_tbl_get(stru_icp67 *p_icp67) { - if(p_method && p_method->iec_point_tbl_get_cb) + if(p_icp67->method.iec_point_tbl_get_cb) { - p_method->iec_point_tbl_get_cb(p_icp67, g_local_iec_info_get.info_addr); + p_icp67->method.iec_point_tbl_get_cb(p_icp67, g_local_iec_info_get.info_addr); } g_flag[3] = 0; } -LOCAL void test_time_set(stru_icp67 *p_icp67, stru_genneral_method *p_method) +LOCAL void test_time_set(stru_icp67 *p_icp67) { stru_ti_5 tm = {0}; @@ -995,40 +995,40 @@ LOCAL void test_time_set(stru_icp67 *p_icp67, stru_genneral_method *p_method) tm.min = ptm->tm_min; tm.ms = ptm->tm_sec * 1000 + tt.tv_usec / 1000; - if(p_method && p_method->time_set_cb) + if(p_icp67->method.time_set_cb) { - p_method->time_set_cb(p_icp67, &tm); + p_icp67->method.time_set_cb(p_icp67, &tm); } g_flag[5] = 0; } -LOCAL void test_self_check_get(stru_icp67 *p_icp67, stru_genneral_method *p_method) +LOCAL void test_self_check_get(stru_icp67 *p_icp67) { - if(p_method && p_method->self_check_get_cb) + if(p_icp67->method.self_check_get_cb) { - p_method->self_check_get_cb(p_icp67); + p_icp67->method.self_check_get_cb(p_icp67); } g_flag[6] = 0; } -LOCAL void test_upgrade_start(stru_icp67 *p_icp67, stru_genneral_method *p_method) +LOCAL void test_upgrade_start(stru_icp67 *p_icp67) { - if(p_method && p_method->upgrade_start_cb) + if(p_icp67->method.upgrade_start_cb) { - p_method->upgrade_start_cb(p_icp67, 2); // 主板固件升级 + p_icp67->method.upgrade_start_cb(p_icp67, 2); } g_flag[9] = 0; } -LOCAL void test_file(stru_icp67 *p_icp67, stru_genneral_method *p_method) +LOCAL void test_file(stru_icp67 *p_icp67) { if(g_local_file.sub_cmd == 1) { - p_method->dir_read_cb(p_icp67, (uint8_t *)g_local_file.temp_str.c_str(), g_local_file.temp_str.size(), NULL, NULL); + p_icp67->method.dir_read_cb(p_icp67, (uint8_t *)g_local_file.temp_str.c_str(), g_local_file.temp_str.size(), NULL, NULL); g_local_file.dir_name = g_local_file.temp_str; } @@ -1038,7 +1038,7 @@ LOCAL void test_file(stru_icp67 *p_icp67, stru_genneral_method *p_method) { if(g_dir_info_vec[i].name == g_local_file.temp_str) { - p_method->file_read_act_cb(p_icp67, (uint8_t *)g_local_file.temp_str.c_str(), g_local_file.temp_str.size()); + p_icp67->method.file_read_act_cb(p_icp67, (uint8_t *)g_local_file.temp_str.c_str(), g_local_file.temp_str.size()); g_local_file.file_name = g_local_file.temp_str; break; @@ -1052,7 +1052,7 @@ LOCAL void test_file(stru_icp67 *p_icp67, stru_genneral_method *p_method) uint32_t file_size = 0; file_size_get(file_name.c_str(), &file_size); - p_method->file_write_act_cb(p_icp67, (uint8_t *)g_local_file.temp_str.c_str(), g_local_file.temp_str.size(), 0, file_size, 0); + p_icp67->method.file_write_act_cb(p_icp67, (uint8_t *)g_local_file.temp_str.c_str(), g_local_file.temp_str.size(), 0, file_size, 0); } g_flag[11] = 0; @@ -1061,8 +1061,8 @@ LOCAL void test_file(stru_icp67 *p_icp67, stru_genneral_method *p_method) void self_ptl_method_task() { - stru_genneral_method *p_method = self_ptl_method_ptr_get(); stru_icp67 *p_icp67 = self_ptl_icp67_ptr_get(); + bool any_active = false; for(auto it = g_map_local_test.begin(); it != g_map_local_test.end(); it++) { @@ -1071,7 +1071,7 @@ void self_ptl_method_task() continue; } - it->second(p_icp67, p_method); + it->second(p_icp67); } } diff --git a/src/system/libself_ptl/src/self_ptl.cpp b/src/system/libself_ptl/src/self_ptl.cpp index c968e4b..472c9c0 100644 --- a/src/system/libself_ptl/src/self_ptl.cpp +++ b/src/system/libself_ptl/src/self_ptl.cpp @@ -4,6 +4,13 @@ #include "method.h" #include "self_ptl.h" #include "myDatacenter.h" +#include +#include + +#define SELF_PTL_BUF_SIZE 2048 +#define SELF_PTL_TEMP_SIZE 256 +#define IEC_APCI_MIN_LEN 4 +#define IEC_FRAME_OVERHEAD 2 typedef struct { @@ -11,7 +18,8 @@ typedef struct uint16_t wptr; uint16_t size; uint16_t cnt; - uint8_t buf[2048]; + uint8_t buf[SELF_PTL_BUF_SIZE]; + pthread_mutex_t mutex; }stru_self_rx; typedef struct @@ -20,8 +28,7 @@ typedef struct stru_icp67 icp67; stru_genneral_method method; stru_self_rx icp67_rx; - stru_self_rx iec_rx; - uint8_t temp_buf[2048]; + uint8_t temp_buf[SELF_PTL_BUF_SIZE]; }stru_self_ptl; stru_self_ptl g_self_ptl = @@ -65,21 +72,17 @@ stru_self_ptl g_self_ptl = { .rptr = 0, .wptr = 0, - .size = 2048, - .cnt = 0, - }, - .iec_rx = - { - .rptr = 0, - .wptr = 0, - .size = 2048, + .size = SELF_PTL_BUF_SIZE, .cnt = 0, + .mutex = PTHREAD_MUTEX_INITIALIZER, }, + }; stru_self_ptl_cfg_data g_self_ptl_cfg_data = {}; + stru_genneral_method *self_ptl_method_ptr_get() { return &g_self_ptl.method; @@ -103,6 +106,7 @@ LOCAL void put_rx_data(stru_self_rx *p_slef_rx, uint8_t *p_rx, uint16_t len) return; } + pthread_mutex_lock(&p_slef_rx->mutex); for(uint16_t i = 0; i < len; i++) { p_slef_rx->buf[p_slef_rx->wptr] = p_rx[i]; @@ -114,9 +118,10 @@ LOCAL void put_rx_data(stru_self_rx *p_slef_rx, uint8_t *p_rx, uint16_t len) p_slef_rx->cnt--; p_slef_rx->rptr = (p_slef_rx->rptr + 1) % p_slef_rx->size; - // LOG_E("put_rx_data cnt %d, rptr %d, wptr %d", p_slef_rx->cnt, p_slef_rx->rptr, p_slef_rx->wptr); + LOG_E("put_rx_data overflow cnt %d, rptr %d, wptr %d", p_slef_rx->cnt, p_slef_rx->rptr, p_slef_rx->wptr); } } + pthread_mutex_unlock(&p_slef_rx->mutex); } LOCAL void get_rx_data(stru_self_rx *p_slef_rx, uint8_t *p_data, uint16_t *p_data_len) @@ -127,6 +132,7 @@ LOCAL void get_rx_data(stru_self_rx *p_slef_rx, uint8_t *p_data, uint16_t *p_dat return; } + pthread_mutex_lock(&p_slef_rx->mutex); uint16_t pos = p_slef_rx->rptr; for(uint16_t i = 0; i < p_slef_rx->cnt; i++) @@ -136,6 +142,7 @@ LOCAL void get_rx_data(stru_self_rx *p_slef_rx, uint8_t *p_data, uint16_t *p_dat } (*p_data_len) = p_slef_rx->cnt; + pthread_mutex_unlock(&p_slef_rx->mutex); } LOCAL int self_ptl_iec104_check_ctrl(stru_iec104_apci *p) @@ -145,7 +152,7 @@ LOCAL int self_ptl_iec104_check_ctrl(stru_iec104_apci *p) return ERR_FRAME; } - if(p->len > 4) + if(p->len > IEC_APCI_MIN_LEN) { if((p->ctrl1 & 0x01) == 0 && (p->ctrl3 & 0x01) == 0) { @@ -205,47 +212,160 @@ LOCAL int self_ptl_iec104_chech_asdu(stru_iec104_apci *p) return 0; } +LOCAL uint8_t iec101_calc_cks(uint8_t *p_data, uint16_t len) +{ + uint8_t cks = 0; + for(uint16_t i = 0; i < len; i++) + { + cks += p_data[i]; + } + + return cks; +} + +LOCAL int self_ptl_search_iec101_short(uint8_t *p_data, uint16_t len, uint16_t i, uint16_t *p_valid_len) +{ + if(p_data[i] != IEC_START_2) + { + return -1; + } + + if(i + 6 <= len && p_data[i + 5] == IEC_TAIL) + { + uint8_t cks_calc = iec101_calc_cks(p_data + i + 1, 3); + if(p_data[i + 4] == cks_calc) + { + *p_valid_len = 6; + return 0; + } + } + + if(i + 5 <= len && p_data[i + 4] == IEC_TAIL) + { + uint8_t cks_calc = iec101_calc_cks(p_data + i + 1, 2); + if(p_data[i + 3] == cks_calc) + { + *p_valid_len = 5; + return 0; + } + } + + return -1; +} + +LOCAL int self_ptl_search_iec101_long(uint8_t *p_data, uint16_t len, uint16_t i, uint16_t *p_valid_len) +{ + if(p_data[i] != IEC_START_1) + { + return -1; + } + + if(i + 4 > len) + { + return -2; + } + + if(p_data[i + 1] != p_data[i + 2] || p_data[i + 3] != IEC_START_1) + { + return -1; + } + + uint8_t l = p_data[i + 1]; + uint16_t total = l + 6; + if(i + total > len) + { + return -2; + } + + if(p_data[i + total - 1] != IEC_TAIL) + { + return -1; + } + + uint8_t cks_exp = p_data[i + total - 2]; + uint8_t cks_calc = iec101_calc_cks(p_data + i + 4, l); + if(cks_exp != cks_calc) + { + return -1; + } + + *p_valid_len = total; + return 0; +} + +LOCAL int self_ptl_search_iec104(uint8_t *p_data, uint16_t len, uint16_t i, uint16_t *p_valid_len) +{ + if(p_data[i] != IEC_START_1) + { + return -1; + } + + if(i + sizeof(stru_iec104_apci) > len) + { + return -2; + } + + stru_iec104_apci *p_apci = (stru_iec104_apci *)&p_data[i]; + + if(p_apci->len + IEC_FRAME_OVERHEAD + i > len) + { + return -2; + } + + int ret = self_ptl_iec104_check_ctrl(p_apci); + if(ret == ERR_FRAME) + { + return -1; + } + + if(ret == I_FRAME && 0 != self_ptl_iec104_chech_asdu(p_apci)) + { + return -1; + } + + *p_valid_len = p_apci->len + IEC_FRAME_OVERHEAD; + return 0; +} + LOCAL int self_ptl_search_iec_frame(uint8_t *p_data, uint16_t len, uint16_t *p_pos, uint16_t *p_valid_len) { if(NULL == p_data || 0 == len || NULL == p_pos || NULL == p_valid_len) { - // LOG_E("self_ptl_search_iec_frame p_data NULL or len 0 or p_pos NULL or p_valid_len NULL"); - return -1; + return -1; } for(uint16_t i = 0; i < len; i++) { - if(i + sizeof(stru_iec104_apci) > len) + int ret; + + ret = self_ptl_search_iec101_short(p_data, len, i, p_valid_len); + if(ret == 0) + { + *p_pos = i; + return 0; + } + + ret = self_ptl_search_iec101_long(p_data, len, i, p_valid_len); + if(ret == 0) + { + *p_pos = i; + return 0; + } + if(ret == -2) { break; } - stru_iec104_apci *p_apci = (stru_iec104_apci *)&p_data[i]; - - if(p_apci->start != IEC_START) + ret = self_ptl_search_iec104(p_data, len, i, p_valid_len); + if(ret == 0) { - continue; + *p_pos = i; + return 0; } - - if(p_apci->len + 2 + i > len) + if(ret == -2) { break; } - - int ret = self_ptl_iec104_check_ctrl(p_apci); - if(ret == ERR_FRAME) - { - continue; - } - - if(ret == I_FRAME && 0 != self_ptl_iec104_chech_asdu(p_apci)) - { - continue; - } - - *p_pos = i; - *p_valid_len = p_apci->len + 2; - return 0; } return -1; @@ -333,17 +453,21 @@ LOCAL void self_ptl_search_frame(uint8_t *p_rx, uint16_t len, stru_icp67 *p_icp6 { if(NULL == p_rx || 0 == len || NULL == p_icp67) { - LOG_E("self_ptl_search_frame p_rx NULL or len 0 or p_icp67 NULL or p_data NULL or p_data_len NULL"); + LOG_E("self_ptl_search_frame p_rx NULL or len 0 or p_icp67 NULL"); return; } put_rx_data(&g_self_ptl.icp67_rx, p_rx, len); - put_rx_data(&g_self_ptl.iec_rx, p_rx, len); uint16_t data_len = 0; uint16_t pos = 0; uint16_t valid_len = 0; int ret = -1; + bool searched = false; + + get_rx_data(&g_self_ptl.icp67_rx, g_self_ptl.temp_buf, &data_len); + uint16_t icp67_consumed = 0; + uint16_t iec_consumed = 0; if(p_icp67->search_frame_cb) { @@ -351,61 +475,70 @@ LOCAL void self_ptl_search_frame(uint8_t *p_rx, uint16_t len, stru_icp67 *p_icp6 { pos = 0; valid_len = 0; - get_rx_data(&g_self_ptl.icp67_rx, g_self_ptl.temp_buf, &data_len); - ret = p_icp67->search_frame_cb(g_self_ptl.temp_buf, data_len, &pos, &valid_len); + ret = p_icp67->search_frame_cb(g_self_ptl.temp_buf + icp67_consumed, data_len - icp67_consumed, &pos, &valid_len); if(0 == ret) { - g_self_ptl.icp67_rx.rptr += (pos + valid_len); - g_self_ptl.icp67_rx.rptr %= g_self_ptl.icp67_rx.size; - g_self_ptl.icp67_rx.cnt -= (pos + valid_len); - - stru_head *p_head = (stru_head *)&g_self_ptl.temp_buf[pos]; + searched = true; + icp67_consumed += (pos + valid_len); + + stru_head *p_head = (stru_head *)&g_self_ptl.temp_buf[icp67_consumed - valid_len]; if(p_head->dev_addr == DEV_MAINTENANCE_ADDR) { uint32_t interface = com_channel_interface_get(ENUM_COMM_TCP_S_0); - self_ptl_data_tx(g_self_ptl.temp_buf + pos, valid_len, (void *)&interface); + self_ptl_data_tx(g_self_ptl.temp_buf + icp67_consumed - valid_len, valid_len, (void *)&interface); } else { if(p_icp67->decode_cb) { - p_icp67->decode_cb(p_icp67, g_self_ptl.temp_buf + pos, valid_len); + p_icp67->decode_cb(p_icp67, g_self_ptl.temp_buf + icp67_consumed - valid_len, valid_len); } } } }while(ret == 0); } - get_rx_data(&g_self_ptl.icp67_rx, g_self_ptl.temp_buf, &data_len); - self_ptl_search_first_head(g_self_ptl.temp_buf, data_len, 0x67, &pos); - g_self_ptl.icp67_rx.rptr += pos; - g_self_ptl.icp67_rx.rptr %= g_self_ptl.icp67_rx.size; - g_self_ptl.icp67_rx.cnt -= pos; - do { pos = 0; valid_len = 0; - get_rx_data(&g_self_ptl.iec_rx, g_self_ptl.temp_buf, &data_len); - ret = self_ptl_search_iec_frame(g_self_ptl.temp_buf, data_len, &pos, &valid_len); + ret = self_ptl_search_iec_frame(g_self_ptl.temp_buf + iec_consumed, data_len - iec_consumed, &pos, &valid_len); if(0 == ret) { - g_self_ptl.iec_rx.rptr += (pos + valid_len); - g_self_ptl.iec_rx.rptr %= g_self_ptl.iec_rx.size; - g_self_ptl.iec_rx.cnt -= (pos + valid_len); + searched = true; + iec_consumed += (pos + valid_len); uint32_t interface = com_channel_interface_get(ENUM_COMM_TCP_S_0); - self_ptl_data_tx(g_self_ptl.temp_buf + pos, valid_len, (void *)&interface); + self_ptl_data_tx(g_self_ptl.temp_buf + iec_consumed - valid_len, valid_len, (void *)&interface); } } while (ret == 0); + + if(searched) + { + uint16_t total_consumed = (icp67_consumed > iec_consumed) ? icp67_consumed : iec_consumed; + g_self_ptl.icp67_rx.rptr += total_consumed; + g_self_ptl.icp67_rx.rptr %= g_self_ptl.icp67_rx.size; + g_self_ptl.icp67_rx.cnt -= total_consumed; + + return; + } + + uint16_t icp67_head_pos = 0; + uint16_t iec_head_1_pos = 0; + uint16_t iec_head_2_pos = 0; + + self_ptl_search_first_head(g_self_ptl.temp_buf, data_len, 0x67, &icp67_head_pos); + self_ptl_search_first_head(g_self_ptl.temp_buf, data_len, IEC_START_1, &iec_head_1_pos); + self_ptl_search_first_head(g_self_ptl.temp_buf, data_len, IEC_START_2, &iec_head_2_pos); + + uint16_t discard = (icp67_head_pos < iec_head_1_pos) ? icp67_head_pos : iec_head_1_pos; + discard = (discard < iec_head_2_pos) ? discard : iec_head_2_pos; - get_rx_data(&g_self_ptl.iec_rx, g_self_ptl.temp_buf, &data_len); - self_ptl_search_first_head(g_self_ptl.temp_buf, data_len, IEC_START, &pos); - g_self_ptl.iec_rx.rptr += pos; - g_self_ptl.iec_rx.rptr %= g_self_ptl.iec_rx.size; - g_self_ptl.iec_rx.cnt -= pos; + g_self_ptl.icp67_rx.rptr += discard; + g_self_ptl.icp67_rx.rptr %= g_self_ptl.icp67_rx.size; + g_self_ptl.icp67_rx.cnt -= discard; } void self_ptl_data_rx(uint8_t *p_data) @@ -639,38 +772,26 @@ void self_ptl_init() stru_genneral_method *p_method = &g_self_ptl.method; - icp67_set_ao_get_cb(&p_method->ao_get_cb); - icp67_set_ao_pop_out_cb(p_method->ao_pop_out_cb); - icp67_set_ao_set_cb(&p_method->ao_set_cb); - icp67_set_iec_point_tbl_get_cb(&p_method->iec_point_tbl_get_cb); - icp67_set_iec_point_tbl_pop_out_cb(p_method->iec_point_tbl_pop_out_cb); - icp67_set_time_set_cb(&p_method->time_set_cb); - icp67_set_self_check_get_cb(&p_method->self_check_get_cb); - icp67_set_self_check_pop_out_cb(p_method->self_check_pop_out_cb); - icp67_set_upgrade_start_cb(&p_method->upgrade_start_cb); + icp67_set_ao_pop_out_cb(p_icp67, p_method->ao_pop_out_cb); + icp67_set_iec_point_tbl_pop_out_cb(p_icp67, p_method->iec_point_tbl_pop_out_cb); + icp67_set_self_check_pop_out_cb(p_icp67, p_method->self_check_pop_out_cb); - icp67_set_dir_read_cb(&p_method->dir_read_cb); - icp67_set_dir_pop_out_cb(p_method->dir_pop_out_cb); - icp67_set_file_read_act_cb(&p_method->file_read_act_cb); - icp67_set_file_read_act_confirm_cb(p_method->file_read_act_confirm_cb); - icp67_set_file_read_cb(p_method->file_read_cb); - icp67_set_file_read_confirm_cb(&p_method->file_read_confirm_cb); - icp67_set_file_write_act_cb(&p_method->file_write_act_cb); - icp67_set_file_write_act_confirm_cb(p_method->file_write_act_confirm_cb); - icp67_set_file_write_cb(&p_method->file_write_cb); - icp67_set_file_write_confirm_cb(p_method->file_write_confirm_cb); - icp67_set_file_write_end_cb(p_method->file_write_end_cb); - icp67_set_file_write_end_confirm_cb(&p_method->file_write_end_confirm_cb); + icp67_set_dir_pop_out_cb(p_icp67, p_method->dir_pop_out_cb); + icp67_set_file_read_act_confirm_cb(p_icp67, p_method->file_read_act_confirm_cb); + icp67_set_file_read_cb(p_icp67, p_method->file_read_cb); + icp67_set_file_write_act_confirm_cb(p_icp67, p_method->file_write_act_confirm_cb); + icp67_set_file_write_confirm_cb(p_icp67, p_method->file_write_confirm_cb); + icp67_set_file_write_end_cb(p_icp67, p_method->file_write_end_cb); - icp67_set_zip_dir_pop_out_cb(p_method->zip_dir_pop_out_cb); - icp67_set_zip_file_pop_out_cb(p_method->zip_file_pop_out_cb); + icp67_set_zip_dir_pop_out_cb(p_icp67, p_method->zip_dir_pop_out_cb); + icp67_set_zip_file_pop_out_cb(p_icp67, p_method->zip_file_pop_out_cb); - icp67_set_mx_trans_cb(p_method->mx_trans_cb); - icp67_set_st_trans_cb(p_method->st_trans_cb); - icp67_set_dd_trans_cb(p_method->dd_trans_cb); - icp67_set_soe_trans_cb(p_method->soe_trans_cb); - icp67_set_fault_trans_cb(p_method->fault_trans_cb); - icp67_set_mx_change_cb(p_method->mx_change_cb); + icp67_set_mx_trans_cb(p_icp67, p_method->mx_trans_cb); + icp67_set_st_trans_cb(p_icp67, p_method->st_trans_cb); + icp67_set_dd_trans_cb(p_icp67, p_method->dd_trans_cb); + icp67_set_soe_trans_cb(p_icp67, p_method->soe_trans_cb); + icp67_set_fault_trans_cb(p_icp67, p_method->fault_trans_cb); + icp67_set_mx_change_cb(p_icp67, p_method->mx_change_cb); } // 你原有的分割函数,完全不动 @@ -755,21 +876,21 @@ void self_ptl_signal_change_callback(std::string saddr, SIGNAL_CTRL_STEP step, u { if(step == SIGNAL_CTRL_STEP::DIRECT) { - if(g_self_ptl.method.ao_set_cb) + if(g_self_ptl.icp67.method.ao_set_cb) { for(uint32_t i = 0; i < p_self_cfg_data->ao_vec.size(); i++) { stru_self_ptl_cfg_param_data *p = &p_self_cfg_data->ao_vec.at(i); if(p->p_param && p->p_param->base.saddr == saddr) { - uint8_t temp[256] = {0}; + uint8_t temp[SELF_PTL_TEMP_SIZE] = {0}; stru_ti_1_2_data_info *p_data_info = (stru_ti_1_2_data_info *)temp; p_data_info->data_addr = p->p_param->base.inf; p_data_info->data_type = p->p_param->type; p_data_info->data_len = dc_get_data_type_len(p->p_param->type); std::string val = dc_get_signal_val(p->vec_p_data[0], p->p_param->type); strcpy((char *)p_data_info->data, val.c_str()); - g_self_ptl.method.ao_set_cb(p_icp67, temp, 1); + g_self_ptl.icp67.method.ao_set_cb(p_icp67, temp, 1); break; } }