ModbusTCP 聚合端口 9502 说明
用途
9502 是新增的 ModbusTCP 聚合入口,用于第三方只建立一个 TCP 客户端就访问四个 485 通道下的从机设备。
现有端口保持不变:
502:集中器宿主机参数,Unit ID=2555502:COM16502:COM27502:COM38502:COM4
Unit ID 映射规则
1~64->COM1 / ID 1~6465~128->COM2 / ID 1~64129~192->COM3 / ID 1~64193~254->COM4 / ID 1~62
示例:
Unit ID=1->COM1 / ID1Unit ID=64->COM1 / ID64Unit ID=65->COM2 / ID1Unit ID=193->COM4 / ID1Unit ID=254->COM4 / ID62
兼容性说明
9502只用于聚合访问从机设备,不承担集中器宿主机参数访问- 宿主机参数仍然通过
502 + Unit ID=255访问 - 原有
5502/6502/7502/8502访问方式不受影响
当前边界
由于 ModbusTCP Unit ID 只有 1 字节,本方案在 9502 上最多只支持到 Unit ID=254,因此 COM4 当前最多映射到本地 ID=62。
当前现场每路只使用到 32 台设备,9502 方案可以满足现有需求;如果后续 COM4 需要稳定支持 63/64 号设备,需要重新设计聚合协议。
第三方对接示例报文
第三方接入时,建议统一使用标准 Modbus TCP 帧格式:
Transaction ID:调用方自定义,响应原样带回Protocol ID:固定0x0000Length:按标准 Modbus TCP PDU 长度填写Unit ID:这里填写9502方案下的全局设备 ID
全局 ID 计算公式:
Global Unit ID = (COM - 1) * 64 + Local ID
例如:
COM1 ID1->1COM2 ID1->65COM2 ID5->69COM3 ID10->138COM4 ID1->193COM4 ID32->224
示例1:读取 COM1 ID1
目标:
- 实际设备:
COM1 / ID1 - 聚合 Unit ID:
1 - 功能码:
03 - 起始地址:
0x0000 - 读取数量:
2个寄存器
请求报文:
00 01 00 00 00 06 01 03 00 00 00 02字段拆解:
00 01:Transaction ID00 00:Protocol ID00 06:Length01:Unit ID,表示COM1 ID103:读保持寄存器00 00:起始地址00 02:读取 2 个寄存器
示例响应:
00 01 00 00 00 07 01 03 04 12 34 56 78说明:
- 响应里的
Unit ID仍然是01 04表示后面有4个数据字节,即2个寄存器12 34、56 78只是示例寄存器值
pymodbus 示例:
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient("192.168.1.100", port=9502)
client.connect()
result = client.read_holding_registers(address=0x0000, count=2, slave=1)
print(result.registers)
client.close()示例2:读取 COM2 ID1
目标:
- 实际设备:
COM2 / ID1 - 聚合 Unit ID:
65 - 功能码:
03 - 起始地址:
0x0000 - 读取数量:
2个寄存器
请求报文:
00 02 00 00 00 06 41 03 00 00 00 02说明:
41十六进制即十进制659502收到后会自动路由到6502对应的COM2 ID1- 响应时仍然返回
41,不会改回本地01
pymodbus 示例:
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient("192.168.1.100", port=9502)
client.connect()
result = client.read_holding_registers(address=0x0000, count=2, slave=65)
print(result.registers)
client.close()示例3:写单个寄存器到 COM2 ID5
目标:
- 实际设备:
COM2 / ID5 - 聚合 Unit ID:
69 - 功能码:
06 - 寄存器地址:
0x0010 - 写入值:
0x1234
标准请求报文:
00 03 00 00 00 06 45 06 00 10 12 34当前实现响应报文:
00 03 00 00 00 06 45 06 00 10 00 01说明:
45十六进制即十进制69- 当前实现支持标准
0x06报文格式,第三方按标准格式发即可 - 响应保持聚合 Unit ID
45 - 当前代码对
0x06的响应格式沿用现有实现,最后两个字节返回的是确认后的寄存器数量字段表现,不建议第三方依赖这两个字节承载“原值回显”的语义
pymodbus 示例:
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient("192.168.1.100", port=9502)
client.connect()
result = client.write_register(address=0x0010, value=0x1234, slave=69)
print(result)
client.close()示例4:写多个寄存器到 COM4 ID1
目标:
- 实际设备:
COM4 / ID1 - 聚合 Unit ID:
193 - 功能码:
10 - 起始地址:
0x0064 - 写入寄存器值:
0x000A、0x0014
请求报文:
00 04 00 00 00 0B C1 10 00 64 00 02 04 00 0A 00 14响应报文:
00 04 00 00 00 06 C1 10 00 64 00 02说明:
C1十六进制即十进制19300 0B表示后续长度为11字节00 02表示写入2个寄存器04表示后面有4个数据字节
pymodbus 示例:
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient("192.168.1.100", port=9502)
client.connect()
result = client.write_registers(address=0x0064, values=[0x000A, 0x0014], slave=193)
print(result)
client.close()示例5:读取 COM4 ID32
目标:
- 实际设备:
COM4 / ID32 - 聚合 Unit ID:
224 - 功能码:
03 - 起始地址:
0x0000 - 读取数量:
2
请求报文:
00 05 00 00 00 06 E0 03 00 00 00 02说明:
E0十六进制即十进制224224 = 193 + 31,对应COM4 ID32
示例6:目标从机无响应时的异常报文
如果 9502 路由到目标从机后等待超时,当前实现会返回标准 Modbus TCP 异常码 0x0B。
例如请求 COM2 ID1:
请求:
00 06 00 00 00 06 41 03 00 00 00 02异常响应:
00 06 00 00 00 03 41 83 0B说明:
41仍然是外部请求看到的聚合 Unit ID83表示03功能码的异常响应0B表示Gateway Target Device Failed to Respond
第三方接入建议
- 第三方如果已经支持标准 Modbus TCP,直接把端口改为
9502、把Unit ID改成全局 ID 即可 - 建议优先使用标准
03/04/10/05/0F报文;06请求可正常下发,但当前响应沿用现有兼容实现,若第三方严格校验标准回显,建议优先改用10 - 宿主机参数访问不要走
9502,仍然走502 + Unit ID=255 - 若现场未来要扩展到
COM4 ID63/64,请提前确认协议升级方案,不能继续默认沿用9502当前映射