<修改> 1、优化icp67模块;2、优化self_ptl应用库
This commit is contained in:
parent
ec424d7f0f
commit
2c10cbbe7c
|
|
@ -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 设置
|
||||
|
|
@ -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
|
||||
```
|
||||
|
|
@ -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 双缓冲
|
||||
改动大,暂缓。
|
||||
|
|
@ -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` 是一个功能完整但架构老旧的嵌入式协议库。核心编解码和重传逻辑是可靠的,主要问题集中在**全局单例耦合**和**可配置性不足**两个层面。最高优先级的改进是将全局回调表实例化,使其从"单设备绑定"升级为"多实例可复用"的协议引擎,从而支撑多通道场景(主板与多采样板同时通信)。
|
||||
|
|
@ -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 系统的协议集成层,承担了**双协议解复用**、**信号注册分发**、**回调桥接**三大核心职责。当前实现功能完备,但在线程安全和多实例扩展方面存在明显短板。最高优先级的三项改进——回调实例化、生产/调试分离、临界区保护——可以解决当前架构中最关键的可靠性和可扩展性问题。
|
||||
|
|
@ -2,8 +2,33 @@
|
|||
|
||||
---
|
||||
|
||||
## 2026-06-15
|
||||
## 2026-06-16: ICP67 模块多实例重构
|
||||
|
||||
**来源**:[libicp67模块分析](./工程/libicp67模块分析.md)
|
||||
|
||||
### 修复项
|
||||
|
||||
1. **全局回调表单例化** — 将 `g_genneral_method` 从 static 全局变量移入 `stru_icp67.method`。26 个 setter 改为实例化接口(`stru_icp67 *` 第一参数)。删除 `general_method.h`、`icp67_get_genneral_method()`。所有 decode 函数改为 `p_icp67->method.xxx_cb` 回调。
|
||||
|
||||
2. **重传竞态修复** — `icp67_timer_handler` 中 `resend_cnt++`/`tm_cnt=0`/`tm_cnt++` 移入 `rtx_sem` 保护区。
|
||||
|
||||
3. **发送覆盖防御** — `icp67_rtx_flag_set` 增加 TX_FLAG 重复设置 LOG_E 警告。
|
||||
|
||||
4. **空桩填充** — `icp67_decode_ti_4`、`icp67_decode_ti_203` 改为 LOG_E + ICP67_RX_FLAG 设置。
|
||||
|
||||
5. **硬编码清理** — 所有魔数替换为命名宏(`ICP67_TX_BUF_SIZE`、`ICP67_MD5_LEN`、`ICP67_TM_TICK_MS`/`ICP67_TM_OUT_MS`、`ICP67_HEAD_OVERHEAD`/`ICP67_FRAME_OVERHEAD` 等)。
|
||||
|
||||
6. **配置参数宏化** — 超时/重试/缓冲/定时器 tick 统一在 `myIcp67.h` 中用 `#define` 管理。
|
||||
|
||||
7. **sender 函数迁移** — 12 个内部 sender 函数从 `general_method.cpp` 迁入 `icp67.cpp`,`icp67_init` 中初始化。
|
||||
|
||||
**状态**:✅ 已完成
|
||||
**涉及文件**:`myIcp67.h`, `icp67.h`, `icp67.cpp`, `general_method.cpp`, `self_ptl.cpp`, `method.cpp`, `general_method.h`(已删除)
|
||||
|
||||
**设计决策**:
|
||||
- pack(1) 不转换(ARM/x86 小端固定,风险收益比不成立)
|
||||
- TI_11 len==11 注释不启(子函数已各自处理标志)
|
||||
- dispatch map(`g_map_ti_decode` 等)保持 static(read-only,多实例安全)
|
||||
### #11 libcom_channel + libcom_scan 合并为 libcom_decode
|
||||
|
||||
**问题**:两个模块紧耦合(com_channel 调 com_recv_data,com_scan 调 com_channel_interface_get),且 app_comm_channel 线程为空壳
|
||||
|
|
@ -195,3 +220,31 @@
|
|||
**涉及文件**:`ws_method.h`, `ws_method.cpp`, `web_server.cpp`
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## 2026-06-16: Self_PTL 缺陷优化
|
||||
|
||||
**来源**:[libself_ptl模块分析](./工程/libself_ptl模块分析.md)
|
||||
|
||||
### 修复项
|
||||
|
||||
1. **D4 测试命令分离** — `self_ptl_method_task()` 增加 `g_self_ptl_test_active` 守卫,仅当 CLI 触发测试命令(`cmd_self_ptl` 设置 flag)时才进入遍历;TIMER2 先检查 active 标志再调用。
|
||||
|
||||
2. **D2 环形缓冲区加锁** — `stru_self_rx` 增加 `pthread_mutex_t mutex` 字段,`put_rx_data`/`get_rx_data` 操作加锁保护。
|
||||
|
||||
3. **D3 溢出日志启** — `put_rx_data` 溢出处理中原被注释的 `LOG_E` 已启。
|
||||
|
||||
4. **D8 SBO 超时** — `stru_signal_ctrl` 增加 `select_time_ms` + `sbo_timeout_ms` 字段。`dc_check_ctrl_valid` 在 SELECT 时记录时间戳。新增 `dc_signal_check_sbo_timeout()` 函数。`self_ptl_task()` 每定时器 tick 检查 SBO 状态,超时(默认 30s)自动回退到 READY。
|
||||
|
||||
5. **D6 硬编码清理** — `2048` → `SELF_PTL_BUF_SIZE`,`256` → `SELF_PTL_TEMP_SIZE`,IEC-104 APCI 魔数 → `IEC_APCI_MIN_LEN`/`IEC_FRAME_OVERHEAD`。
|
||||
|
||||
### 未处理
|
||||
|
||||
- **D7 双缓冲优化** — 改动大、风险高,暂缓。
|
||||
- **D5 IEC-104 帧校验** — 已完整,无需处理。
|
||||
- **D9 滑窗丢弃** — 逻辑正确,无需处理。
|
||||
|
||||
**状态**:✅ 已完成
|
||||
**涉及文件**:`self_ptl.cpp`, `method.cpp`, `myDatacenter.h`, `dc_signal.cpp`
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "myIcp67.h"
|
||||
|
||||
|
||||
|
||||
|
||||
stru_genneral_method* icp67_get_genneral_method();
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue