
云快充协议本身不难读:报文头加业务体,一帧一答。真正上线之后订单对不上、状态不准、电量有差,问题几乎都不在报文格式里,而在几个文档不会写的地方。
下面这 8 个点,来自实际项目里反复出现的对接故障。按顺序排查,大多数「协议不通」的问题能在半小时内定位。
一、粘包与拆包:TCP 是字节流,不是消息队列
最常见的错误是按固定长度读。recv 返回多少字节由网络决定,不保证正好是一帧。桩连着发两帧时,一次读取可能拿到一帧半;网络慢时,一帧可能分三次到。
正确做法只有一个:先读报文头,从头里解析出报文长度,再按长度读业务体。缓冲区里剩下的字节留给下一次循环。
- 现象:白天正常,夜里偶发解析失败;日志里出现半截报文或字段值明显异常;
- 排查:把收到的原始字节按十六进制完整打印,对比长度字段与实际字节数;
- 修复:写一个累积缓冲区,只在下游凑够一帧时才交给解析器。
二、心跳正常不等于设备可用
心跳只证明这条 TCP 连接还活着。枪口有没有故障、功率模块是否降额、急停有没有被按下,是另外几件事。很多平台把「心跳正常」直接显示成「在线」,客户到现场才发现枪是坏的。
建议把设备状态拆成三层:连接状态(心跳)、业务状态(枪口与故障码)、可用状态(能否下发启动指令)。三层都满足才算「可充电」。
三、时钟不同步,订单时间会错位
桩的本地时钟会漂移。便宜的板子一个月能差几分钟,断过电的差几小时也不稀奇。订单的开始时间如果取桩端时间,峰谷计费就会算错,跨零点时甚至会把两天的账算到一天里。
- 在登录或心跳的应答里做对时,让桩定期校时;
- 平台侧一律以服务端时间为准入库,桩端时间只作为辅助字段保留;
- 对账时如果发现某笔订单的时间与相邻订单差得离谱,先查时钟,别急着怀疑业务逻辑。
四、三份电量:电表读数、平台累计、订单电量
同一个枪口,往往能拿到三个不同的电量数字:电表累计读数、实时数据帧的累计值、订单结算电量。三者有小幅差异是正常的,差异变大就要查。
| 数据来源 | 特点 | 用途 |
|---|---|---|
| 电表读数 | 精度最高,掉电不丢 | 结算与计量争议的最终依据 |
| 实时数据累计 | 上报周期内可能被截断 | 监控与趋势,不用于结算 |
| 订单电量 | 一次充电的起止差值 | 计费与开票 |
做法是:以订单电量为结算口径,同时保存电表起止读数;两者差异超过阈值(比如 2%)自动标红,转人工复核,而不是让系统默默按某一个数值算过去。
五、离线订单补传
断网时桩会在本地存交易记录,网络恢复后补传。这里有三个坑:
- 补传时间戳被覆盖。有些实现把补传时间当成交易时间写库,结果所有离线订单都堆在同一分钟;
- 重复补传。网络抖动时同一笔订单传两遍,如果没有唯一流水号去重,订单量会翻倍;
- 补传顺序乱。后发生的交易先入库,按时间统计会出错。
唯一可靠的解法是:以桩生成的交易流水号作为主键去重,并且用报文里的交易发生时间入库,不用接收时间。
六、枪口状态机别只靠一个字段
空闲、插枪未充、充电中、故障、离线,这五个状态之间的跳变,靠单个状态字段判断经常出错。比如充电结束的瞬间,状态帧可能还没更新,平台已经开始计费或停止计费,一分钟的差就是一笔小账。
更稳的方式是同时看三样东西:枪口状态帧、实时数据里是否有电流、订单是否处于进行中。三者矛盾时以「有电流」为最优先,其次看订单。
七、远程指令要幂等
远程启动、远程停止这类指令,失败方式不止一种:桩没收到、收到了但执行失败、执行成功但应答丢了。平台如果只做「发送—等应答」,超时后就重试,很容易出现重复启动。
- 指令带唯一 ID,桩侧对同一 ID 只执行一次;
- 超时后不要盲目重发,先查一次枪口状态,确认没执行再重试;
- 所有指令与其结果都落库,出问题时能还原「谁在什么时候下发了什么」。
八、日志要留多久
协议类问题,半年后还会被翻出来。客户说某天的订单不对,你需要能拿出当天的原始报文。
- 原始报文至少保留 90 天,压缩存储即可,一帧通常不到 100 字节;
- 订单相关的报文与状态变更建议长期保留,与订单同生命周期;
- 日志里如果带手机号、VIN,入库前脱敏,避免合规风险。
一张自查清单
| 检查项 | 合格标准 |
|---|---|
| 拆包 | 先读头再按长度读体,任意分片都不解析失败 |
| 设备状态 | 连接、业务、可用三层分开存,前端不混用 |
| 时钟 | 有心跳对时,订单时间取服务端时间 |
| 电量口径 | 订单电量为准,电表读数同存,差异超阈值告警 |
| 离线补传 | 流水号去重,用交易时间而非接收时间 |
| 枪口状态 | 状态帧、电流、订单三者交叉校验 |
| 远程指令 | 带唯一 ID、桩侧幂等、超时先查后重试 |
| 日志 | 原始报文 90 天以上,敏感字段脱敏 |
最后
协议对接的难点很少在「能不能通」,而在「通了之后对不对得上」。能通只说明两边讲同一种语言,对得上才说明对同一件事的理解一致。
我们的充电运营平台核心支持云快充协议,兼容 OCPP 1.6/2.0 与主流厂商私有协议。上面这 8 条,是我们自己在接入不同品牌桩时踩完之后写进系统里的。