EMS - 电表 / 智能插座 TCP 通讯协议

张开发
2026/4/16 7:47:54 15 分钟阅读

分享文章

EMS - 电表 / 智能插座 TCP 通讯协议
基于你提供的协议文档 实战日志汇总 4 个核心命令码的完整定义、报文格式、交互逻辑、实战例子覆盖所有通讯场景。一、协议核心规则必看所有交互遵循以下统一规则​固定起始符​所有报文以0xA5开头​响应码规则​响应命令码 0x80 请求命令码如请求0x01→ 响应0x81请求0x03→ 响应0x83​字节序​所有int32类型数据为​小端字节序​低字节在前高字节在后​精度规则​所有电参数电压 / 电流 / 功率的真实值 报文值 ÷ 100精度 0.01​默认模式​电表上电默认模式0被动查询仅响应0x03查询不主动发0x04​通讯方向​电表 TCP 客户端主动发起连接EMS TCP 服务端监听端口被动接收连接二、命令码全解析按交互顺序1. 命令码0x01连接验证核心定义TCP 连接建立后电表向 EMS 发起的​身份验证命令​是所有后续通讯的前置步骤必须先完成验证才能进行数据交互。通讯方向电表 → EMS客户端 → 服务端报文格式表格字段起始符命令码数据长度数据设备 SN取值0xA50x010x10(16)13 字节设备 SN 3 字节预留实战请求报文你的日志示例hexA5 01 10 30 39 30 33 32 35 5A 30 30 30 30 31 00 00 00​响应报文EMS → 电表表格字段起始符命令码数据长度错误码取值0xA50x810x01(1)0x00 成功非 0 失败实战响应报文你的日志示例hexA5 81 01 00​交互逻辑电表上电建立 TCP 连接到 EMS电表发送0x01连接验证报文携带设备 SNEMS 校验 SN 合法后回复0x81 00验证成功电表打印「连接验证成功」进入数据交互阶段注意事项未完成0x01验证时电表会忽略所有0x02/0x03命令若 EMS 回复非0x00错误码电表会断开 TCP 并重连2. 命令码0x02数据采集模式设置核心定义EMS 向电表发送的​模式控制命令​用于切换电表的功率上报方式是触发0x04主动上报的唯一入口。通讯方向EMS → 电表服务端 → 客户端模式定义协议原文表格模式值含义0默认模式功率变化时不主动上报仅响应0x03查询1主动上报模式功率变化超阈值时电表主动发0x04上报报文格式表格字段起始符命令码数据长度模式值取值0xA50x020x01(1)0x00/0x01实战请求报文模式 0默认被动查询A5 02 01 00模式 1主动上报常用A5 02 01 01响应报文电表 → EMS表格字段起始符命令码数据长度错误码取值0xA50x820x01(1)0x00 设置成功实战响应报文hexA5 82 01 00​交互逻辑EMS 在0x01验证成功后发送0x02模式设置命令电表收到后切换对应模式回复0x82 00确认成功模式立即生效电表按新规则上报数据注意事项电表默认模式 0不发送0x02命令电表永远不会发送0x04模式 1 下仍可正常发送0x03查询不影响主动上报逻辑模式切换后电表会保存当前模式断电重启后默认恢复模式 03. 命令码0x03EMS 查询插座 / 电表当前功率核心定义EMS 主动拉取电表实时电参数的​被动查询命令​是模式 0 下唯一的获取数据方式模式 1 下仍可使用。通讯方向EMS → 电表服务端 → 客户端报文格式表格字段起始符命令码数据长度数据取值0xA50x030x00(0)无实战请求报文你的日志示例hexA5 03 00​响应报文电表 → EMS表格字段起始符命令码数据长度数据段电参数取值0xA50x830x0C~0x1C(12~28)按协议定义的 int32 小端数据数据段字段定义协议原文表格字节范围字段名数据类型说明byte0-byte3voltageint32A 相电压精度 0.01V真实值 报文值 ÷100byte4-byte7currentint32A 相电流精度 0.01A真实值 报文值 ÷100byte8-byte11powerint32总有功功率精度 0.01W真实值 报文值 ÷100byte12-byte15powerReactiveint32总无功功率精度 0.01W智能插座无此字段byte16-byte19powerAint32A 相有功功率精度 0.01W智能插座无此字段byte20-byte23powerBint32B 相有功功率精度 0.01W智能插座无此字段byte24-byte27powerCint32C 相有功功率精度 0.01W智能插座无此字段实战响应报文你的日志示例hexA5 83 1C A5 5B 00 00 B2 00 00 00 02 1F 00 00 8F 60 FF FF 02 1F 00 00 00 00 00 00 00 00 00 00​报文解析示例按小端 精度规则表格字段报文字节小端原始 int32 值真实值÷100电压A5 5B 00 000x00005BA5 23461234.61V电流B2 00 00 000x000000B2 1781.78A总有功功率02 1F 00 000x00001F02 793879.38W总无功功率8F 60 FF FF0xFFFF608F -40817​**-408.17W**​容性负载A 相有功02 1F 00 000x00001F02 793879.38WB/C 相有功00 00 00 000​0.00W​空载交互逻辑EMS 定时如 1s / 次发送0x03查询命令电表收到后打包当前电参数回复0x83响应EMS 解析0x83数据段获取实时功率数据注意事项模式 0 下必须通过0x03才能获取数据电表不会主动上报智能插座场景数据长度为 12 字节仅电压 / 电流 / 总有功无后续无功 / 分相字段三相电表场景数据长度为 28 字节7 个 int32包含分相功率4. 命令码0x04插座 / 电表主动上报功率核心定义电表在模式 1下功率变化超阈值时主动向 EMS 上报的功率数据命令无需 EMS 查询实现实时推送。通讯方向电表 → EMS客户端 → 服务端触发条件EMS 通过0x02命令将电表设置为模式 1电表检测到当前功率变化超过预设阈值如 ±10W报文格式表格字段起始符命令码数据长度数据段电参数取值0xA50x040x0C~0x1C(12~28)与0x83响应数据段完全一致实战报文示例hexA5 04 1C A5 5B 00 00 B2 00 00 00 02 1F 00 00 8F 60 FF FF 02 1F 00 00 00 00 00 00 00 00 00 00​交互逻辑EMS 发送0x02 01设置模式 1电表回复0x82 00电表实时监测功率当变化超阈值时主动发送0x04报文EMS 接收0x04报文按0x83的解析逻辑提取数据无需回复响应注意事项​**仅模式 1 下会触发0x04**​默认模式 0 下电表不会发送0x04的数据段格式、解析规则与0x83完全一致可复用同一套解析代码主动上报阈值可在电表端配置默认通常为 ±5~10W三、完整通讯流程两种模式1. 模式 0默认被动查询完整流程plaintext1. TCP连接建立 2. 电表 → EMS发送0x01连接验证带SN 3. EMS → 电表回复0x81 00验证成功 4. EMS → 电表定时发送0x03查询命令 5. 电表 → EMS回复0x83带功率数据 6. 循环步骤4-5直到TCP连接断开​2. 模式 1主动上报完整流程plaintext1. TCP连接建立 2. 电表 → EMS发送0x01连接验证带SN 3. EMS → 电表回复0x81 00验证成功 4. EMS → 电表发送0x02 01设置模式1主动上报 5. 电表 → EMS回复0x82 00设置成功 6. 电表功率变化超阈值 → 主动发送0x04带数据 7. EMS接收0x04数据同时仍可发送0x03查询 8. 直到TCP连接断开​四、常见问题汇总对应你的测试场景为什么日志里只有 0x03 命令电表默认模式 0仅响应0x03查询你未发送0x02命令所以不会出现0x02/0x04解决在 EMS 端发送0x02 01切换模式 1即可触发0x02/0x04交互电表报 errno 128网络不可达电表仍在连接你的笔记本内网 IP如 192.168.12.27跨网场景下无法路由解决修改电表连接目标为 frp 内网穿透的公网 IP 映射端口0x04 主动上报不出现未通过0x02设置模式 1或功率变化未超过阈值解决发送0x02 01并给电表加负载如插电器触发功率变化报文解析数值不对未按小端字节序解析或未除以 100解决严格按「小端重组 → 转十进制 →÷100」的规则解析五、实战测试用例一键跑通全命令测试目标跑通 4 个命令码验证完整协议步骤 1启动模拟 EMS 服务Pythonpython运行import socket HOST 0.0.0.0 PORT 10241 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((HOST, PORT)) s.listen() print(f✅ 模拟EMS服务启动监听{HOST}:{PORT}) conn, addr s.accept() with conn: print(f 电表已连接{addr}) # 1. 处理0x01连接验证 data conn.recv(1024) print(f 收到0x01验证报文{data.hex()}) # 回复0x81 00验证成功 conn.send(bytes.fromhex(A5 81 01 00)) print( 发送0x81 00连接验证成功) # 2. 发送0x02 01设置模式1主动上报 mode_cmd bytes.fromhex(A5 02 01 01) conn.send(mode_cmd) print( 发送0x02 01设置主动上报模式) # 接收0x82响应 data conn.recv(1024) print(f 收到0x82响应{data.hex()}) # 3. 循环处理0x03查询/0x04上报 while True: data conn.recv(1024) if not data: break print(f 收到报文{data.hex()}) # 若收到0x03查询回复0x83模拟电表 if data[1] 0x03: resp bytes.fromhex(A5 83 1C A5 5B 00 00 B2 00 00 00 02 1F 00 00 8F 60 FF FF 02 1F 00 00 00 00 00 00 00 00 00 00) conn.send(resp) print( 发送0x83功率数据响应)​步骤 2启动内网穿透svnproxycmdcd C:\Users\Acrel\Desktop\ems_visitor svnproxy.exe -c frpc_ss_ems.ini​步骤 3修改电表连接目标为穿透公网 IP上电测试电表日志会依次出现0x01→0x81→0x02→0x82→0x03→0x83/0x044 个命令码全部跑通

更多文章