Files

251 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CCU–POS VTK 串口结算功能设计说明(草案)
版本:v0.1
协议参考:`vtk-protocol-en-1.23.pdf`VTK protocol 1.23
---
## 1. 应用场景概述
- **角色**
- **VMCVending Machine Controller**:本项目中的 **CCU 主控**,负责充电控制、计量和向 POS 发起扣款 / 结算请求。
- **POS 终端**:支持 VTK 协议的支付终端,完成银行卡 / 钱包扣款,并把结果回传给 CCU。
- **业务流程(高层逻辑)**
1. 车主在充电桩侧操作“启动充电”(扫码 / 刷卡 / 远程指令等),CCU 准备启动充电流程。
2. CCU 根据配置计算 **预扣款金额**(例如 50 元,可配置)。
3. CCU 通过 **串口上的 VTK 协议** 向 POS 发送“预扣款请求”消息,请求冻结该金额。
4. POS 完成预扣并返回“通过 / 拒绝 / 超时”等结果:
- 通过:CCU 进入正常充电流程。
- 拒绝:CCU 不启动充电,向用户提示相应原因。
5. 充电完成(正常结束 / 故障结束 / 用户中止)后,CCU 计算 **最终充电金额**(按电量 / 时间 / 固定服务费等计费规则)。
6. CCU 再次通过 VTK 协议向 POS 发送“结算请求”,携带最终金额以及会话标识。
7. POS 根据最终金额完成扣款 / 退款(与预扣差额),返回结算结果。
8. CCU 记录最终结算结果到本地订单 / 日志系统,并更新 UI / 平台状态。
- **通信方式**
- 物理层:**串口(UART)**,波特率等推荐按 VTK 文档默认值:`115200 8N1,无流控`
- 链路层:可选择直接使用原始串口帧结构(1F 起始 + 长度 + 协议号 + TLV + CRC16)。
- 应用层:严格遵循 VTK base protocol`0x96FB/0x97FB`)的 TLV 编码要求。
---
## 2. VTK 协议要点(与本项目相关部分)
### 2.1 基本帧格式(串口模式)
参考文档第 2 章,串口下消息帧结构:
- `Start`1 字节,固定 `0x1F`
- `Length`:2 字节,大端,表示“后续所有数据长度(不含 CRC16)”
- `Protocol discriminator`2 字节,大端
- `0x96FB`VMC → POS
- `0x97FB`POS → VMC
- `Application message`0..65533 字节,**BER TLV**ISO/IEC 8825-1
- `CRC16`2 字节,大端,CRC16-CCITT(初始值 0xFFFF),从 `Start` 到 TLV 最后一字节
### 2.2 TLV 参数
VTK base protocol 中应用消息是多个 TLV 参数的组合:
- `Tag`:1~3 字节(此协议中基本为单字节 Tag,例如 `0x01` Message name、`0x04` Amount 等)
- `Length`1~3 字节
- `Value`:具体值(ASCII / Binary / UTF-8
本项目中 **优先使用的 Tag**(参考文档 3.1):
- `0x01`Message nameASCII 3)—— 如 `"CDP"`, `"CRD"`, `"INF"`, `"PRS"` 等。
- `0x03`Operation numberASCII 数字,8 位)—— 可做一次充电会话的 ID。
- `0x04`Amount in minor currency unitASCII,金额的“最小货币单位”,例如分)。
- `0x11`:Local time(可选,用于时钟同步)。
- `0x12`System information(可选,用于 POS 侧展示桩信息)。
> 后续业务实现只需先支持必要的 Tag,留出扩展空间即可。
---
## 3. 业务消息与状态机设计(草案)
### 3.1 关键业务实体
- **ChargeSession(充电会话)**
- `sessionId`:对应 VTK 的 Operation numberTag 0x03)。
- `gunNo`:枪号(0/1/...)。
- `preAuthAmount`:预扣款金额(单位:分)。
- `finalAmount`:最终金额(单位:分)。
- `state``Idle / PreAuthPending / PreAuthOk / Charging / SettlePending / Settled / Failed`
- **VTKOperation**
- `messageName`Tag 0x01):例如 `"CDP"`(预扣款)、`"CRD"`(结算)等。
- `direction``VMC→POS``POS→VMC`
- `tlvList`:一个 TLV 参数列表。
### 3.2 建议消息映射(可根据实际对接调整)
- **预扣款请求**CCU→POS
- Message name (`0x01`)`"CDP"`(或自定义,如 `"CHP"`Charge PreAuth
- Operation number (`0x03`):本次充电会话 ID(ASCII 数字)
- Amount (`0x04`):预扣款金额,单位“分”,例如 5000 表示 50.00 元
- **预扣款响应**POS→CCU
- Message name (`0x01`)`"CDP"`(同请求)
- Operation number (`0x03`):与请求一致
- Amount (`0x04`):实际冻结金额(可与请求相同)
- 结果参数:可以使用 System information 或自定义扩展的 Simple data block`0x0D`)中定义结果码,例如:
- `0`Approved
- `1`Declined
- `2`Timeout
- **结算请求**CCU→POS
- Message name (`0x01`)`"CRD"`Charge Debit / Refund
- Operation number (`0x03`):与本会话相同
- Amount (`0x04`):实际消费总金额(分)
- **结算响应**POS→CCU
- Message name (`0x01`)`"CRD"`
- Operation number (`0x03`):同请求
- Amount (`0x04`):最终扣款金额
- 结果码(同上)
### 3.3 CCU 侧状态机(简化)
1. **Idle**
- 等待用户操作(插枪、刷卡、平台下发启动命令)。
2. **PreAuthPending**
- 组包 VTK `CDP` 预扣款请求,通过串口发给 POS。
- 等待响应(配置超时,例如 15s),期间可处理心跳 / 重发。
3. **PreAuthOk**
- 收到 POS 批准预扣款,更新内部状态,允许充电流程进入 **Charging**
4. **Charging**
- 现有充电流程不变(BMS/流控/计量)。
5. **SettlePending**
- 充电结束,计算 `finalAmount`,组包 VTK `CRD` 结算请求,发送给 POS。
- 等待响应;失败可重试若干次或降级处理(仅记录本地订单,提示用户到平台查询)。
6. **Settled / Failed**
- Settled:记录成功订单,通知平台/界面。
- Failed:记录失败原因(网络/卡拒绝/超时),可与平台对账或人工处理。
---
## 4. 模块划分与文件结构建议
`CCU601E_RUN/app/pos_vtk` 目录下建议创建如下模块(后续实现时使用):
1. **基础协议层**
- `vtk_frame.c / vtk_frame.h`
- 串口帧封装 / 解封装(1F 起始、长度、协议号、CRC16)。
- CRC16-CCITT 实现(参考文档第 5 章)。
- `vtk_tlv.c / vtk_tlv.h`
- TLV 编码 / 解码(Tag/Length/Value)。
- 提供便捷接口:`addAsciiParam(tag, QString)`, `getAsciiParam(tag, ...)` 等。
2. **业务协议层**
- `vtk_pos_protocol.c / vtk_pos_protocol.h`
- 构造/解析 **预扣款请求/响应**、**结算请求/响应**、**系统信息** 等应用消息:
- `buildPreAuthRequest(session, preAuthAmount, QByteArray &outFrame)`
- `parsePreAuthResponse(const QByteArray &frame, VtkResult &out)`
- `buildSettleRequest(...)` / `parseSettleResponse(...)`
3. **会话与状态机层**
- `pos_vtk_service.c / pos_vtk_service.h`
- 维护每把枪的 `ChargeSession` 状态:
- `posVtk_startPreAuth(gunNo, amount)`
- `posVtk_onFrameReceived(frame)` —— 调用基础解析,然后驱动状态机
- `posVtk_notifyChargeEnd(gunNo, finalAmount)` —— 进入结算流程
- 与现有 `flowctrl_task`/`collect_task`/`meter_calculate`/`plat_comm_task` 对接。
4. **串口接入层**
- 若已有串口任务(如 `uart_task`),只需在串口接收回调中把 VTK 帧交给 `vtk_frame` 层解析。
- 若没有,可在 `app_init``plat_comm_task` 下新增 POS 串口任务:
- 周期读取串口缓存、拼帧、调用 `posVtk_onFrameReceived`
---
## 5. 与现有 CCU 模块的集成点
- **启动充电**:在当前启动充电逻辑中(flowctrl / bms / collect),增加“调用 `posVtk_startPreAuth`”步骤,并根据其结果决定是否允许进入充电状态。
- **停止充电**:在充电任务或计量模块中,当确定实际消费金额后,调用 `posVtk_notifyChargeEnd` 进入结算流程。
- **告警与 UI 提示**
- 预扣款失败:在 UI 或平台上显示“支付预授权失败,请重试或更换支付方式”。
- 结算失败:记录订单异常状态,提示用户可联系运营方处理。
---
## 6. 后续实施步骤建议
1. **确认业务映射**:与 POS 提供方确认使用的 Message nameCDP/CRD/INF 等)、结果码格式以及参数集合。
2. **实现基础协议层**`vtk_frame` + `vtk_tlv`,并通过单元测试校验:
- CRC 计算正确。
- TLV 编解码对齐文档。
3. **实现预扣款 / 结算消息构造与解析**`vtk_pos_protocol`
4. **实现 POS 会话状态机**`pos_vtk_service`,并与现有充电流程打通(只改入口/出口逻辑,尽量不动核心 BMS/MDU 代码)。
5. **集成串口任务**:选定 UART 口,完成收发调试(先用日志工具验证 VTK 帧格式)。
6. **与实际 POS 联调**:根据联调结果调整错误码处理、超时重试策略等。
---
## 7. 示例报文
以下示例仅展示 **TLV 内容和串口帧结构**,CRC16 按实现自动计算,示例中不逐字列出。
### 7.1 预扣款请求(CDP
- 业务参数:
- Message name`"CDP"`Tag 0x01
- Operation number`"12345"`Tag 0x03,十进制 ASCII
- Amount`"5000"`Tag 0x04,表示 50.00 元)
- TLV 区段(十六进制):
- `01 03 43 44 50`
- Tag=0x01Len=0x03Value="CDP"
- `03 05 31 32 33 34 35`
- Tag=0x03Len=0x05Value="12345"
- `04 04 35 30 30 30`
- Tag=0x04Len=0x04Value="5000"
- 串口帧结构:
- `1F` 起始字节
- `00 LL` Length2 字节,大端,= ProtocolDisc + TLV 长度)
- `96 FB` Protocol discriminatorVMC→POS
- `01 03 43 44 50 03 05 31 32 33 34 35 04 04 35 30 30 30` TLV 数据
- `CC CC` CRC16-CCITT(由代码计算)
### 7.2 结算请求(CRD
- 参数示意:
- Message name`"CRD"`0x01
- Operation number:与预扣款相同 `"12345"`0x03
- Amount:最终金额 `"4200"`0x04,表示 42.00 元)
TLV 结构与上例相同,仅值不同。
### 7.3 响应报文(POS→CCU
- 假设 POS 对预扣款返回:
- Message name`"CDP"`
- Operation number`"12345"`
- Amount`"5000"`
- ResultTag 0x0DLength=1Value=0x00Approved
TLV 区段:
- `01 03 43 44 50` CDP
- `03 05 31 32 33 34 35` Operation number
- `04 04 35 30 30 30` Amount
- `0D 01 00` Simple data block,结果码=0
串口帧中的 Protocol discriminator 为 `0x97FB`POS→VMC)。
---
> 说明:本文件为第一版设计草案和实现说明,后续在实际联调和业务确认过程中,可根据需要继续细化:
> - 完善错误码与 POS 侧状态码的映射
> - 增加更多业务消息(如 INF、PRS 等)
> - 完善异常流程(网络断开、POS 重启、CRC 错误等)的处理策略。