JavaScript基于OCPP 1.6连接EV充电桩时WebSocket帧错误排查
问题排查与修复方案
核心错误原因
错误WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH的直接原因是:调用ws.send()时传入了原始JavaScript数组,而ws库要求WebSocket消息必须是序列化后的字符串(OCPP协议要求JSON格式)或Buffer。直接传数组会被ws库错误解析为不符合规范的WebSocket帧,导致payload长度异常。
代码修复步骤
1. 修复消息发送逻辑
所有ws.send()的内容必须先通过JSON.stringify()序列化为JSON字符串,这是OCPP over WebSocket的强制要求。示例修改如下:
// 原错误代码(BootNotification响应) ws.send([ 3, uuidv4(), Action, { status: "Accepted", currentTime: this.get_current_time(), interval: 14400, }, ]); // 修复后代码 ws.send(JSON.stringify([ 3, uuidv4(), Action, { status: "Accepted", currentTime: this.get_current_time(), interval: 14400, }, ]));
同理,所有其他ws.send()调用(包括RemoteStartTransaction指令、Heartbeat响应、错误处理中的消息)都需要用JSON.stringify()包裹。
2. 优化错误处理与连接重置
在WebSocket错误事件中,不要尝试继续发送消息(此时连接已处于异常状态),应主动关闭连接,让充电桩按OCPP协议逻辑重连:
ws.on("error", (error) => { console.error("WebSocket error:", error); // 仅在连接处于开放状态时主动关闭,触发充电桩重连 if (ws.readyState === ws.OPEN) { ws.close(1002, "Invalid frame format"); } });
3. 完整修复后的核心逻辑片段
switch (Action) { case "BootNotification": ws.send(JSON.stringify([ 3, uuidv4(), Action, { status: "Accepted", currentTime: this.get_current_time(), interval: 14400, }, ])); ws.send(JSON.stringify([ 2, uuidv4(), "RemoteStartTransaction", { connectorId: 1, idTag: "738961FE", }, ])); break; case "Heartbeat": ws.send(JSON.stringify([ 3, uuidv4(), Action, { currentTime: this.get_current_time() }, ])); break; case "StatusNotification": ws.send(JSON.stringify([3, uuidv4(), Action, {}])); break; default: console.log("Unsupported action:", data); }
额外注意事项
- OCPP 1.6 over WebSocket要求所有消息必须是UTF-8编码的JSON字符串,禁止直接发送JS对象或数组。
- 接收充电桩消息时的
JSON.parse(data.toString())解析逻辑是正确的,发送时需保持对称序列化。 - 充电桩会遵循BootNotification响应中返回的
interval参数定期发起重连,无需额外编写重连触发逻辑。
内容的提问来源于stack exchange,提问作者fyxov01010
相关产品推荐
相关产品推荐

