<修改> 1、优化icp67模块;2、优化self_ptl应用库

This commit is contained in:
ypc 2026-06-16 14:57:45 +08:00
parent ec424d7f0f
commit 2c10cbbe7c
16 changed files with 1596 additions and 804 deletions

View File

@ -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 设置

View File

@ -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
```

View File

@ -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 双缓冲
改动大,暂缓。

View File

@ -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` 是一个功能完整但架构老旧的嵌入式协议库。核心编解码和重传逻辑是可靠的,主要问题集中在**全局单例耦合**和**可配置性不足**两个层面。最高优先级的改进是将全局回调表实例化,使其从"单设备绑定"升级为"多实例可复用"的协议引擎,从而支撑多通道场景(主板与多采样板同时通信)。

View File

@ -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 系统的协议集成层,承担了**双协议解复用**、**信号注册分发**、**回调桥接**三大核心职责。当前实现功能完备,但在线程安全和多实例扩展方面存在明显短板。最高优先级的三项改进——回调实例化、生产/调试分离、临界区保护——可以解决当前架构中最关键的可靠性和可扩展性问题。

View File

@ -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` 等)保持 staticread-only多实例安全
### #11 libcom_channel + libcom_scan 合并为 libcom_decode
**问题**两个模块紧耦合com_channel 调 com_recv_datacom_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`

View File

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

View File

@ -1,8 +0,0 @@
#pragma once
#include "myIcp67.h"
stru_genneral_method* icp67_get_genneral_method();

View File

@ -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()

View File

@ -1,573 +1,88 @@
#include "general_method.h"
#include "icp67.h"
#include "myLog.h"
#include <map>
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);
}

View File

@ -1,6 +1,5 @@
#include "icp67.h"
#include "myLog.h"
#include "general_method.h"
#include <vector>
#include <string>
@ -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<uint8_t, icp67_decode_cb> 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<stru_st_info> st_info_vec;
std::vector<stru_mx_info> 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);
}

View File

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

View File

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

View File

@ -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

View File

@ -21,6 +21,7 @@
LOCAL std::vector<stru_dir_info> 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<uint16_t, iec_point_tbl_decode> 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<uint8_t, local_test> 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);
}
}

View File

@ -4,6 +4,13 @@
#include "method.h"
#include "self_ptl.h"
#include "myDatacenter.h"
#include <pthread.h>
#include <time.h>
#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;
}
}