这个代码只是转发修改后的保持寄存器数据吧,modbus信号不单单只有保持寄存器
时间: 2024-03-08 18:46:30 浏览: 148
MODBUS 接受数据
是的,这个示例代码只是转发修改后的保持寄存器数据,但是可以根据需要进行修改,以实现转发完整的Modbus信号。下面是修改后的示例代码:
```python
from pymodbus.client.sync import ModbusSerialClient as ModbusClient
from pymodbus.server.sync import ModbusSerialServer as ModbusServer
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSparseDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.payload import BinaryPayloadBuilder, BinaryPayloadDecoder
from pymodbus.constants import Endian
from pymodbus.transaction import ModbusRtuFramer
import serial
import threading
# 串口参数
com1_port = 'COM1'
com1_baudrate = 9600
com2_port = 'COM2'
com2_baudrate = 9600
# 从站地址
slave_address = 1
# 数据存储
coils = ModbusSequentialDataBlock(0, [False] * 100)
discrete_inputs = ModbusSequentialDataBlock(0, [False] * 100)
holding_registers = ModbusSequentialDataBlock(0, [0] * 100)
input_registers = ModbusSequentialDataBlock(0, [0] * 100)
# 创建从站
def create_slave():
store = ModbusSlaveContext(
di=ModbusSparseDataBlock(discrete_inputs),
co=ModbusSparseDataBlock(coils),
hr=ModbusSequentialDataBlock(holding_registers),
ir=ModbusSequentialDataBlock(input_registers))
context = ModbusServerContext(slaves=store, single=True)
return context
# 从站写回调函数
def on_write_coil(address, value):
coils[address] = value
print('on_write_coil: address={}, value={}'.format(address, value))
def on_write_discrete_input(address, value):
discrete_inputs[address] = value
print('on_write_discrete_input: address={}, value={}'.format(address, value))
def on_write_register(address, value):
holding_registers[address] = value
print('on_write_register: address={}, value={}'.format(address, value))
def on_write_input_register(address, value):
input_registers[address] = value
print('on_write_input_register: address={}, value={}'.format(address, value))
# 创建主站
def create_master():
client = ModbusClient(method='rtu', port=com2_port, baudrate=com2_baudrate)
client.connect()
return client
# 串口接收线程函数
def com1_receive_thread(context):
ser = serial.Serial(com1_port, com1_baudrate, timeout=1)
framer = ModbusRtuFramer(client=None)
while True:
data = ser.read(1024)
if data:
framer.processIncomingPacket(data, context[slave_address])
else:
break
ser.close()
# 串口转发线程函数
def com2_forward_thread(client):
while True:
for address in range(len(coils)):
value = coils[address]
client.write_coil(address, value, unit=slave_address)
print('com2_forward_thread: coil address={}, value={}'.format(address, value))
for address in range(len(discrete_inputs)):
value = discrete_inputs[address]
client.write_discrete_input(address, value, unit=slave_address)
print('com2_forward_thread: discrete input address={}, value={}'.format(address, value))
for address in range(len(holding_registers)):
value = holding_registers[address]
builder = BinaryPayloadBuilder(endian=Endian.Big)
builder.add_16bit_int(value)
payload = builder.build()
client.write_registers(address, payload, skip_encode=True, unit=slave_address)
print('com2_forward_thread: holding register address={}, value={}'.format(address, value))
for address in range(len(input_registers)):
value = input_registers[address]
builder = BinaryPayloadBuilder(endian=Endian.Big)
builder.add_16bit_int(value)
payload = builder.build()
client.write_registers(address, payload, skip_encode=True, unit=slave_address, skip_function_code=True)
print('com2_forward_thread: input register address={}, value={}'.format(address, value))
threading.Event().wait(0.1)
# 启动程序
if __name__ == '__main__':
# 创建从站
context = create_slave()
context[slave_address].setValues(1, 0, coils)
context[slave_address].setValues(2, 0, discrete_inputs)
context[slave_address].setValues(3, 0, input_registers)
context[slave_address].setValues(4, 0, holding_registers)
server = ModbusServer(context, framer=ModbusRtuFramer)
server.register(callback=on_write_coil, function_code=1)
server.register(callback=on_write_discrete_input, function_code=2)
server.register(callback=on_write_register, function_code=3)
server.register(callback=on_write_input_register, function_code=4)
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
server_thread.start()
# 创建主站
client = create_master()
# 启动串口接收线程和转发线程
com1_receive_thread = threading.Thread(target=com1_receive_thread, args=(context,))
com1_receive_thread.daemon = True
com1_receive_thread.start()
com2_forward_thread = threading.Thread(target=com2_forward_thread, args=(client,))
com2_forward_thread.daemon = True
com2_forward_thread.start()
# 主线程等待
threading.Event().wait()
```
修改后的代码中,从站的数据存储包括线圈、离散输入、保持寄存器和输入寄存器。同时,创建了四个回调函数分别处理写线圈、写离散输入、写保持寄存器和写输入寄存器的请求。主站的转发线程循环处理所有四种类型的Modbus信号,并使用正确的功能码和数据格式转发给其他设备。
需要注意的是,这里使用了ModbusRtuFramer来处理Modbus RTU帧,因此需要修改从站的创建和主站的连接方式。
阅读全文