Initial commit: CCU621_M firmware project with BLE debug link support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-08 17:28:36 +08:00
commit 9ceb218f80
1597 changed files with 724159 additions and 0 deletions
@@ -0,0 +1,365 @@
# IES 积成平台通信移植方案(CCU601_A → CCU601E_D
本文档基于 **`CCU601_A_20240601\app\platform`** 中积成智通(IESZT)协议实现,对照 **`CCU601E_D\app\plat_comm`** 现有联网框架(`plat_comm_task` + `bs_connect_impl` + `bs_public_impl`),给出在 E 工程中**新增 IES 平台连接**的分阶段实现方案。
---
## 0. 备份说明
已在本机创建工程目录备份(不含 `MDK-ARM\output` 编译产物,以缩短拷贝时间):
| 路径 |
|------|
| `d:\Desktop\NewProject\cursor\EuropeanStandard\CCU601E_D_backup_20260519` |
如需完整含编译输出的备份,可在资源管理器中自行复制整个 `CCU601E_D` 目录。
---
## 1. 源工程(CCU601_AIES 模块概览
### 1.1 文件与职责
| 文件 | 行级规模(约) | 职责 |
|------|----------------|------|
| **`BS_ies_ctrl.h`** | 协议常量 + `S_IES_CTRL_DATA` | 帧类型码 `NT_*`、数据对象、对外 API |
| **`BS_ies_ctrl.c`** | ~560 行 | 回调注册、TCP/4G 建链、登录、收包解帧、私有超时逻辑 |
| **`BS_ies_interface.h/c`** | ~1800+ 行 | **组帧/解帧**:登录、心跳、费率、实时数据、账单、远程启停、对时、FTP 升级、二维码等 |
| **`BS_Task.c/h`** | ~1150 行 | **平台任务总线**:周期发送、双枪调度、`bs_register_callback``Task_BS` 主循环 |
| **`FtpUpdate.c`** | FTP 升级 | 与 `NT_UPDATE_AUTO(0x90)` 配合(A 侧旧 FTP 流程) |
| **`BS_WH_GM5.c`** | 4G 模组 | A 工程 **WH-GM5** 透传/AT**E 工程为 EC200A,不可直接搬** |
### 1.2 协议特征(与 OCPP 差异)
积成协议为 **二进制定长头 + 变长数据域**,非 JSON/WebSocket。
```
帧起始 0x68 | 长度 2B | 序号 1B | 设备地址 16B ASCII | 加密 1B | 数据对象 1B | 帧类型 1B | 数据域 N | 校验 1B
```
- **协议版本**`NT_PTL_VERSION = 37`V3.5
- **帧类型码**:登录 `0x01/0x02`、心跳 `0x03/0x04`、充电实时 `0x11/0x13`、账单 `0x47/0x48`、远程启停 `0x44~0x46`、对时 `0x76`、计费 `0x7D/0x7E`、FTP `0x90` 等(见 `BS_ies_ctrl.h`
- **校验**:序号域至数据域末字节 **累加和**`u8_crc_checkSum`
- **粘包**`v_bs_unpack_handle_ieszt``0x68` 搜头、长度域算整帧长
### 1.3 A 侧任务模型
```mermaid
flowchart TB
subgraph Task_BS
TCP[v_bs_tcp_connect]
LOG[v_ies_logo_on / v_bs_register_req]
SEND[v_bs_send_ctrl]
RECV[v_ies_recv_data → unpack]
PRIV[v_ies_private_crel]
end
subgraph callbacks
IF[BS_ies_interface 组帧]
end
SEND -->|E_BS_CALLBACK_CMD| IF
IF -->|com_read / eth_send| LINK[4G WH_GM5 / 以太网 socket]
```
- **发送**`BS_Task.c``v_bs_send_ctrl(bs_flag)` 按周期/标志调用 `v_bs_callback(cmd, gun)`IES 在 `v_bs_ies_register_callback()` 中注册具体组帧函数。
- **接收**`v_ies_recv_data()``v_bs_unpack_handle_ieszt()``v_bs_rx_cmd_hanle()``u8_recvBuf[22]` 帧类型分发。
- **登录成功**`v_bs_register_ack()` 内置 `u8_register_flag = 1`,并置 `bs_ctrl_data[].u8_log_on_flag`(与 E 的 `u8_log_on_flag` 概念一致)。
---
## 2. 目标工程(CCU601E_D)现状
### 2.1 已有挂钩(未实现)
| 位置 | 内容 |
|------|------|
| **`public_define.h`** | `BS_IES_EN` 默认 **0** |
| **`plat_comm_task.c`** | `MasterFuncArray` 已预留 **`"ieszt"`** 槽位及 7 个回调函数名 |
| **`plat_comm_task.h`** | `#include "plat_comm/ieszt/bs_ies_ctrl.h"``S_BS_IES_CTRL_DATA s_ies_data` |
| **目录** | **`plat_comm/ieszt/` 尚不存在**(编译开启 `BS_IES_EN` 会缺文件) |
E 侧 **`MasterFuncPtl`** 比 A 多一项 **`v_bs_recv_unpack`**(OCPP 未用;IES 可将解帧放在 `v_ies_recv_data` 内,**`v_ies_recv_unpack` 可留空**)。
### 2.2 E 侧应复用的基础设施(禁止重复造轮子)
| 模块 | 用途 |
|------|------|
| **`plat_comm_task.c`** | `v_Plat_Comm` 主循环、FTP/联网分时、`v_set_bs_renew` |
| **`bs_connect_impl.c`** | **`u8_tcp_connect`**、**`v_bs_send`**、**`u16_bs_recv`**4G EC200A + 网口 LwIP/TLS |
| **`bs_public_impl.c`** | 枪状态、**`S_LOG_DATA`** 订单、启停 **`v_bs_charge_action_ctrl`**、未结/掉电 **`s8_plat_get_unsettled_order`** |
| **`meter_calculate`** | 计量订单、EEPROM 临时单、Flash 未结索引 |
| **`flowctrl`** | `u8_bs_get_flow_state`E 已有,替代 A 的 `e_get_flow_rt_state` |
| **`v_ftp_update_action`** | OCPP/平台 FTP 升级;IES `0x90` 需映射到 **`t_ftp_update_info`** + `u8_updata_flag` |
### 2.3 A → E 关键差异对照
| 维度 | CCU601_A | CCU601E_D |
|------|----------|-----------|
| RTOS / 任务 | `Task_BS` + `GetCurSecond` | `v_Plat_Comm` + `get_current_seconds` |
| 4G | WH-GM5、`com_read(COM_PORT_BS)` | **EC200A**`v_ec200a_tcp_app_send/recv` |
| 网口 | `eth_connect` / `CreatSocket` 直连 | **`lwip_tcp_connect`** + `v_bs_eth_close_socket` |
| 订单结构 | **`CHARGE_LOG_T`** | **`S_LOG_DATA`** |
| 双平台控制块 | **`bs_ctrl_data[MAX_BS_NUM]`** | **`s_bs_task_ctrl.s_bs_ctrl[]`** + 可选 **`s_ies_data`** |
| 平台协议 | SDK + IES 二选一或双开 | **OCPP** + 可选 **IES**`MAX_BS_NUM=2` |
| 日志 | `logMsg_bs` | **`Plat_Comm_LOG` / `MYLOG_MSG`** |
---
## 3. 目标架构(移植后)
```mermaid
flowchart TB
subgraph PlatComm
PC[v_Plat_Comm]
M[MasterFuncArray slot: ieszt]
end
subgraph ieszt
CTRL[bs_ies_ctrl.c]
IF[bs_ies_interface.c]
SEND[v_ies_send_ctrl]
end
subgraph impl
CONN[bs_connect_impl]
PUB[bs_public_impl]
end
PC --> M
M --> CTRL
SEND --> IF
IF --> CONN
CTRL --> PUB
CONN --> EC200A[4G EC200A]
CONN --> LWIP[LwIP TCP/TLS]
```
**原则**
1. **IES 只实现「积成二进制协议」**TCP/4G/网口/TLS **一律走 `bs_connect_impl`**
2. **业务数据只通过 `bs_public_impl` + `meter_calculate`** 读写,不在 IES 模块内直接碰 flow 内部结构。
3. **周期发送**可移植 A 的 `E_BS_CALLBACK_CMD` 模型,但计时器挂到 **`s_bs_task_ctrl.s_bs_ctrl[ies_id]`** 或独立 **`S_BS_IES_CTRL_DATA`**,由 **`v_ies_send_ctrl`** 在已登录分支执行(与 OCPP 的 `v_ocpp_send_ctrl` 同级)。
---
## 4. 建议目录与文件清单
**`CCU601E_D/app/plat_comm/ieszt/`**(运行时说明见 **`ieszt/IES积成平台功能说明.md`**,与 **`平台联网任务功能说明.md`** 联动)新建:
| 文件 | 来源 | 说明 |
|------|------|------|
| **`bs_ies_ctrl.h`** | 自 A `BS_ies_ctrl.h` 改编 | 帧类型码、`S_BS_IES_CTRL_DATA`(合并原 `S_IES_CTRL_DATA` + 必要定时器) |
| **`bs_ies_ctrl.c`** | 自 A `BS_ies_ctrl.c` 重构 | 去掉 WH_GM5/CreatSocket;改用 `u8_tcp_connect(id)``v_bs_send``u16_bs_recv` |
| **`bs_ies_interface.h`** | 自 A `BS_ies_interface.h` | 组帧/解帧 API |
| **`bs_ies_interface.c`** | 自 A `BS_ies_interface.c` | 大文件;发送改为 `v_bs_send`;桩号从 `u8_get_str_data(E_STR_PILE_NO)` 获取 |
| **`bs_ies_send.c`**(可选) | 自 A `BS_Task.c` 抽取 | `v_ies_send_ctrl``v_ies_register_callback`、双枪周期逻辑,减小单文件体积 |
| **`bs_ies_adapter.c/h`**(建议新建) | 新写 | **`S_LOG_DATA` ↔ 账单组帧字段**、停止原因 **E_FAULT_* → IESZT_REASON** |
**不迁入 E 工程(或仅参考)**
- `BS_WH_GM5.c/h` → 使用现有 **`ec200a_4g.c`**
- `BS_sdk_*` → 与 IES 无关
- A 版 `FtpUpdate.c` 中与 OCPP 重复部分 → 统一 **`v_ftp_update_action`** + `ec200a_4g_ftp` / `lwip_ftp_upgrade`
---
## 5. 接口映射(MasterFuncPtl 七件套)
| 回调 | 实现要点 |
|------|----------|
| **`v_ies_init_data(U8_T id)`** | `id` 写入 `s_ies_data.u8_bs_flag``v_ies_register_callback()`;清 `s_ies_data`**不要**调用 `v_bs_4G_data_init`(由 `u8_tcp_connect` 统一处理);帧序号 `u16_msgSerialNumber=0` |
| **`v_ies_tcp_connect(void)`** | 返回 **`u8_tcp_connect(s_ies_data.u8_bs_flag)`** 结果;删除 A 中 `v_WH_GM5_init`、独立 `CreatSocket` |
| **`v_ies_logo_on(void)`** | 周期发 **`v_bs_register_req()`**(约 20s);**`v_bs_register_ack`** 内置置位后返回 1;登录超时 6 次 → **`v_set_bs_renew(id)`** + 仅重置 IES 私有数据(**勿全量 `v_ocpp_init_data`** |
| **`v_ies_recv_data(void)`** | `u16_bs_recv(id, buf, len)`;若 `u8_updata_flag` 且 4G FTP 活跃则可直接 return(与 A 一致) |
| **`v_ies_recv_unpack(id, buf, len)`** | **建议空实现**;解帧已在 `v_ies_recv_data` 完成。若未来 UART 分包由外部注入,再迁入 `v_bs_unpack_handle_ieszt` |
| **`v_ies_send_ctrl(void)`** | 移植 A **`v_bs_send_ctrl(ies_flag)`**:登录后心跳、费率、空闲/充电实时、表底、告警、账单、即插即充、离线单等 |
| **`v_ies_private_logic(U8_T id)`** | 心跳无应答计数、登录态维护、**`v_cheak_state_change` 类逻辑**(改调 E 的 `v_bs_log_txFlag_*`)、离线订单 **`s8_plat_get_unsettled_order` 路径**(可选与 OCPP 互斥) |
---
## 6. 数据与业务适配层(`bs_ies_adapter`
### 6.1 订单 / 账单(`NT_BILL_UPLOAD 0x47`
A`v_get_log_data` / `v_gunTmpChgRcd_rd` + `CHARGE_LOG_T``v_bs_bill_pack`
E 建议:
```c
S_LOG_DATA log;
u8_plat_get_real_order(&log, gun) s8_plat_get_unsettled_order(&log, 0);
v_ies_bill_pack_from_log(gun, &log);
```
- **`u8_preTradeNo`**:IES 账单字段与 A 一致处直接 `memcpy`;无平台流水号时用设备流水号或占位规则与运营确认。
- **停充原因**`log.e_stop_reason[0]`**`v_ies_map_stop_reason_to_ieszt()`** 转为 `IESZT_REASON_E`A 已在 `BS_Task.c` 有大表,可迁到 adapter)。
### 6.2 远程启停(`0x44` / `0x46`
A`v_bs_rmt_start/stop` 内调 flow/UI。
E
```c
S_BS_CHAR_CTRL ctrl;
memset(&ctrl, 0, sizeof(ctrl));
ctrl.u16_ctrl_res = E_NORMAL_1002; /* 或映射平台原因 */
v_bs_charge_action_ctrl(gun, E_CHAR_CTRL_STOP, &ctrl);
```
启机需组 **`S_CHAR_LOG_START_DATA`** 后 `E_CHAR_CTRL_START`,与 OCPP RemoteStart 路径对齐,避免双协议冲突(见 §8)。
### 6.3 对时(`NT_CLK_SYNC_REQ 0x76`
A:写 RTC。
E**`v_bs_set_time(&Comm_Time)`**`bs_public_impl` 已有)。
### 6.4 计费模型(`0x05/0x06/0x7D/0x7E`
A:写费率 Flash/共享区。
E:对接 **`meter_calculate` / 费率存储**`u32_meterlog_get_sys_data(E_METERLOG_GET_DATA_FEE_*)` 或现有配置接口),需与产品确认 IES 费率 PDU 与 E 侧 96 时段模型是否一致。
### 6.5 实时数据(`0x11` / `0x13`
字段来源改为:
- 电压电流 SOC`u32_bs_get_sys_data` / `u64_bs_get_sys_data`
- 枪状态:`u8_bs_get_flow_state``E_BS_GET_SYS_DATA_GUN_STATE`
- 电量:`E_BS_GET_SYS_DATA_MEMTER_ELECT`
### 6.6 FTP 升级(`NT_UPDATE_AUTO 0x90`
解析平台下发的 FTP 参数 → 填充 **`t_ftp_update_info`** → 置对应槽位 **`u8_updata_flag=1`** → 由现有 **`v_ftp_update_action`** 执行(4G/网口分支已有)。
---
## 7. 配置与编译集成
### 7.1 宏与工程配置
```c
/* public_define.h */
#define BS_IES_EN (1) /* 使能积成平台 */
#define BS_OCPP_EN (1) /* 可与 OCPP 双平台:槽位 0=OCPP1=IES,由 PLAT_EN 决定 */
```
- Keil / CMake:将 **`plat_comm/ieszt/*.c`** 加入 **PlatComm** 分组。
- 确认 **`plat_comm_task.h`** 中 `S_BS_IES_CTRL_DATA``bs_ies_ctrl.h` 定义一致(或 typedef 别名)。
### 7.2 系统参数(与 A 对齐项)
| 配置项 | A 来源 | E 建议 |
|--------|--------|--------|
| 主站 IP/端口 | `u8_remote_ip` / `u16_remote_port` | 继续用 **`t_sys_fix_cfg`**IES **不用** WebSocket URL,可用 **纯 `tcp://ip:port`** 或单独 **IES 服务器配置项**(若与 OCPP 域名不同,需在配置表增加字段,避免与 `u8_serverA_domain_name` 混用) |
| 桩号 16 字节 | `u8_pile_serial_num` | `u8_get_str_data(E_STR_PILE_NO)` |
| 平台使能 | `bs_type[]` 初始化 | `E_BS_GET_SYS_DATA_PLAT_EN` per 槽位 |
| 联网方式 | `e_network_type` | `E_BS_GET_SYS_DATA_NET_TYPE` |
### 7.3 `MasterFuncArray` 注册示例
与现有 `plat_comm_task.c` 一致,确保 **`BS_IES_EN`** 时槽位与 **`PLAT_EN`** 配置对应,例如:
- 槽位 0OCPP`BS_OCPP_EN`
- 槽位 1IES`BS_IES_EN`
双平台同时使能时,**两路独立 `u8_TCP_connect_flag` / `u8_log_on_flag`**,互不覆盖。
---
## 8. 双平台共存策略(OCPP + IES
| 风险 | 策略 |
|------|------|
| 同一枪被 OCPP RemoteStart 与 IES `0x44` 同时控制 | 产品层约定:**仅一个平台为主**;或 `PLAT_EN` 互斥。代码层在 `v_bs_rmt_start` 中判断 **`u8_bs_get_flow_state==0`** 且 OCPP 未在充。 |
| 离线订单双路上送 | E 未结索引统一 **`unsettled_order_mng`**IES 掉电单走 **`s8_plat_get_unsettled_order`** 时与 OCPP **互斥处理**(同一单不两协议各 Stop 一次)。 |
| 4G UART 占用 | OCPP 与 IES **共用 `bs_connect_impl`** 时,**不能两槽位同时 `u8_netType==0` 各建一条 Socket**,除非运营确认为双连接;通常 **一机一路 4G 一个 TCP****双平台只选其一或网口+4G 分流**。 |
| FTP 与 IES 收包 | 保持 **`plat_comm_task` FTP/联网分时**IES **`v_ies_recv_data`** 在 FTP 周期不解析 IES 帧(与 A 相同 guard)。 |
---
## 9. 分阶段实施计划
### 阶段 1:骨架可编译(1~2 天)
- [ ] 创建 `plat_comm/ieszt/`,迁入 **`bs_ies_ctrl.h`**、精简 **`bs_ies_ctrl.c`**`init/tcp_connect/logo_on/recv/private` 空壳 + `u8_tcp_connect`
- [ ] **`BS_IES_EN=1`** 编译通过;`v_ies_recv_unpack` 空实现
- [ ] 槽位 **`bs_enable=1`** 时能进 `v_Plat_Comm` 建链日志
### 阶段 2:链路 + 登录心跳(2~3 天)
- [ ] 迁入 **`bs_ies_interface.c`** 中:`u8_bs_pack_frm_head``v_bs_register_req/ack``v_bs_heart/ack``u8_crc_checkSum`
- [ ] 收包粘包 **`v_bs_unpack_handle_ieszt`**
- [ ] 实机验证:**Login 0x02**、**Heartbeat 0x04**、平台对时(若有)
### 阶段 3:运营关键帧(3~5 天)
- [ ] **`v_bs_rtd_free` / `v_bs_rtd_chging`** + `v_ies_send_ctrl` 周期表(对齐 A:心跳 20s、充电 30s、空闲 180s 等)
- [ ] **`v_bs_bill_pack`** + adapter 从 **`S_LOG_DATA`**
- [ ] **`v_bs_rmt_start/stop`** → `v_bs_charge_action_ctrl`
- [ ] **`v_bs_bill_upload_ack`** → `v_bs_platform_settlement_confirm` / 清 EEPROM 临时单
### 阶段 4:增强与对齐(按需)
- [ ] 计费模型 `0x7D/0x7E`、二维码 `0x08/0x0A`、故障 `0x15`、表底 `0x31`
- [ ] FTP `0x90``t_ftp_update_info`
- [ ] 掉电未结:与 **`meter_calculate` EEPROM 恢复**、**`s8_plat_get_unsettled_order`** 联调
- [ ] 双枪 `u8_bs_twoGnu_send` 逻辑迁入
### 阶段 5:测试与文档
- [ ] 用例:4G / 网线、单枪/双枪、远程启停、断网重连、充电中离线、掉电上电补单
- [ ] 更新 **`平台联网任务功能说明.md`** 增加 IES 章节
---
## 10. 接收发送伪代码(E 风格)
```c
void v_ies_recv_data(void)
{
U8_T id = s_ies_data.u8_bs_flag;
U8_T buf[512];
U16_T n;
if (s_bs_task_ctrl.s_bs_ctrl[id].u8_updata_flag != 0U
&& s_bs_task_ctrl.s_bs_ctrl[id].u8_netType == 0U) {
return;
}
n = u16_bs_recv(id, buf, sizeof(buf));
if (n > 0U) {
v_bs_unpack_handle_ieszt(buf, (S16_T)n);
}
}
static void v_ies_send_frame(U8_T *frm, U16_T len)
{
v_bs_send(s_ies_data.u8_bs_flag, frm, len);
}
```
---
## 11. 测试验收标准(摘要)
| 编号 | 项 | 通过标准 |
|------|-----|----------|
| T1 | TCP | `PlatComm` 打印 `tcp connect`,平台侧可见连接 |
| T2 | 登录 | 收到 `0x02``u8_log_on_flag=1`,桩号与配置一致 |
| T3 | 心跳 | 周期 `0x03`,平台 `0x04`,断链后 `v_set_bs_renew` 可恢复 |
| T4 | 充电实时 | 充电中 `0x11`、空闲 `0x13` 周期上送,数据与电表一致 |
| T5 | 账单 | 停充后 `0x47`,平台 `0x48` 后本地未结清除 |
| T6 | 远程停 | 平台 `0x46` 后枪停止,原因码正确 |
| T7 | 掉电 | 有 txId 的订单恢复后账单 **transactionId 非 0**(与 OCPP 掉电修复一致) |
---
## 12. 关联文档
| 文档 | 路径 |
|------|------|
| E 联网任务总览 | `plat_comm/平台联网任务功能说明.md` |
| OCPP 模块 | `plat_comm/ocpp/OCPP功能模块说明.md` |
| 4G EC200A | `plat_comm/4g_module/4G模块AT指令配置功能说明.md` |
| 源 IES 协议头 | `CCU601_A_20240601/app/platform/BS_ies_ctrl.h` |
---
*文档版本:2026-05-19;随 `plat_comm/ieszt` 落地情况更新勾选清单。*