-
Notifications
You must be signed in to change notification settings - Fork 1k
Labels
Description
Versions
- Python: 2.7.16
- OS: Debian (Raspberry Pi OS)
- Pymodbus: 2.3.0
- Modbus Hardware (if used): pymodbus client with two pymodbus servers running on RPi's
Pymodbus Specific
- Server: rtu - sync
- Client: rtu - repl
Description
I currently have a RS-485 bus with 3 Raspberry Pi each running pymodbus (1 master/client and 2 slaves/servers). I want to be able to read device information and send broadcast messages in addition to individual commands. I noticed that reading device information is only available with the repl client but broadcast messages result in an error (AttributeError: 'str' object has no attribute 'isError'). It appears the repl client is incorrectly expecting a response from broadcasts. My current work around is using the sync client, and using a separate repl client for device id requests. Can broadcast support be added to the repl client?
Code and Logs
Code
Master:
#!/usr/bin/env python
import serial
import time
from pymodbus.repl.client import ModbusSerialClient as ModbusClient
import logging
#-------------------------------------------#
# Logging
#-------------------------------------------#
FORMAT = ('%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
#-------------------------------------------#
# Client Initialization
#-------------------------------------------#
client = ModbusClient(method='rtu', port='/dev/ttySC0', timeout=2,
baudrate=115200, broadcast_enable=True)
client.connect()
#-------------------------------------------#
# Command testing
#-------------------------------------------#
print(client.read_device_information(read_code=0x02, object_id=4, unit = 1))
time.sleep(0.1)
print(client.write_registers(1, [2, 3, 4], unit=1))
time.sleep(0.1)
print(client.write_registers(1, [2, 3, 4], unit=0))
Slave
#!/usr/bin/env python
import serial
from pymodbus.server.sync import StartSerialServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock, ModbusSparseDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer, ModbusBinaryFramer
# --------------------------------------------------------------------------- #
# Logging
# --------------------------------------------------------------------------- #
import logging
FORMAT = (' %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
def slave_setup():
block = ModbusSequentialDataBlock(0, [17]*100)
slave = dict()
slave[1] = ModbusSlaveContext(di=block, co=block, hr=block, ir=block)
context = ModbusServerContext(slaves=slave, single=False)
identity = ModbusDeviceIdentification()
identity.VendorName = 'Pymodbus'
identity.ProductCode = 'PM'
identity.VendorUrl = 'URL'
identity.ProductName = '#1 Test Slave'
identity.ModelName = 'Research Testbed'
identity.MajorMinorRevision = '2.3.0'
StartSerialServer(context, framer=ModbusRtuFramer, identity=identity,ignore_missing_slaves=True,
port='/dev/ttySC0', timeout=0.1, baudrate=115200, broadcast_enable=True)
if __name__ == "__main__":
slave_setup()
Logs
Master:
DEBUG transaction :115 Current transaction state - IDLE
DEBUG transaction :120 Running transaction 1
DEBUG transaction :219 SEND: 0x1 0x2b 0xe 0x2 0x4 0x71 0x44
DEBUG sync :75 New Transaction state 'SENDING'
DEBUG transaction :228 Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG transaction :304 Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG transaction :233 RECV: 0x1 0x2b 0xe 0x2 0x83 0x0 0x0 0x2 0x4 0xd 0x23 0x31 0x20 0x54 0x65 0x73 0x74 0x20 0x53 0x6c 0x61 0x76 0x65 0x5 0x10 0x52 0x65 0x73 0x65 0x61 0x72 0x63 0x68 0x20 0x54 0x65 0x73 0x74 0x62 0x65 0x64 0xca 0xb
DEBUG rtu_framer :180 Getting Frame - 0x2b 0xe 0x2 0x83 0x0 0x0 0x2 0x4 0xd 0x23 0x31 0x20 0x54 0x65 0x73 0x74 0x20 0x53 0x6c 0x61 0x76 0x65 0x5 0x10 0x52 0x65 0x73 0x65 0x61 0x72 0x63 0x68 0x20 0x54 0x65 0x73 0x74 0x62 0x65 0x64
DEBUG factory :266 Factory Response[ReadDeviceInformationResponse: 43]
DEBUG rtu_framer :115 Frame advanced, resetting header!!
DEBUG transaction :383 Adding transaction 1
DEBUG transaction :394 Getting transaction 1
DEBUG transaction :193 Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
{u'function_code': 43, u'information': {4: '#1 Test Slave', 5: 'Research Testbed'}, u'space left': None, u'object count': 2, u'next object id': 0, u'more follows': 0, u'conformity': 131}
DEBUG transaction :115 Current transaction state - TRANSACTION_COMPLETE
DEBUG transaction :120 Running transaction 2
DEBUG transaction :219 SEND: 0x1 0x10 0x0 0x1 0x0 0x3 0x6 0x0 0x2 0x0 0x3 0x0 0x4 0x3f 0x46
DEBUG rtu_framer :264 Changing state to IDLE - Last Frame End - 1595356416.71, Current Time stamp - 1595356416.81
DEBUG sync :75 New Transaction state 'SENDING'
DEBUG transaction :228 Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
DEBUG transaction :304 Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
DEBUG transaction :233 RECV: 0x1 0x10 0x0 0x1 0x0 0x3 0xd1 0xc8
DEBUG rtu_framer :180 Getting Frame - 0x10 0x0 0x1 0x0 0x3
DEBUG factory :266 Factory Response[WriteMultipleRegistersResponse: 16]
DEBUG rtu_framer :115 Frame advanced, resetting header!!
DEBUG transaction :383 Adding transaction 1
DEBUG transaction :394 Getting transaction 1
DEBUG transaction :193 Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
{u'count': 3, u'function_code': 16, u'address': 1}
DEBUG transaction :115 Current transaction state - TRANSACTION_COMPLETE
DEBUG transaction :120 Running transaction 3
DEBUG transaction :219 SEND: 0x0 0x10 0x0 0x1 0x0 0x3 0x6 0x0 0x2 0x0 0x3 0x0 0x4 0x3d 0xc7
DEBUG rtu_framer :264 Changing state to IDLE - Last Frame End - 1595356416.89, Current Time stamp - 1595356416.99
DEBUG sync :75 New Transaction state 'SENDING'
DEBUG transaction :223 Changing transaction state from 'SENDING' to 'TRANSACTION_COMPLETE'
Traceback (most recent call last):
File "repl_broadcast.py", line 30, in <module>
print(client.write_registers(1, [2, 3, 4], unit=0))
File "/home/pi/.local/lib/python2.7/site-packages/pymodbus/repl/client.py", line 172, in write_registers
if not resp.isError():
AttributeError: 'str' object has no attribute 'isError'
Slave:
DEBUG rtu_framer :180 Getting Frame - 0x2b 0xe 0x2 0x4
DEBUG factory :137 Factory Request[ReadDeviceInformationRequest: 43]
DEBUG rtu_framer :115 Frame advanced, resetting header!!
DEBUG sync :144 send: [ReadDeviceInformationResponse(2)]- 012b0e0283000002040d2331205465737420536c617665051052657365617263682054657374626564ca0b
DEBUG rtu_framer :180 Getting Frame - 0x10 0x0 0x1 0x0 0x3 0x6 0x0 0x2 0x0 0x3 0x0 0x4
DEBUG factory :137 Factory Request[WriteMultipleRegistersRequest: 16]
DEBUG rtu_framer :115 Frame advanced, resetting header!!
DEBUG context :64 validate: fc-[16] address-2: count-3
DEBUG context :90 setValues[16] 2:3
DEBUG sync :144 send: [WriteMultipleRegisterResponse (1,3)]- 011000010003d1c8
DEBUG rtu_framer :180 Getting Frame - 0x10 0x0 0x1 0x0 0x3 0x6 0x0 0x2 0x0 0x3 0x0 0x4
DEBUG factory :137 Factory Request[WriteMultipleRegistersRequest: 16]
DEBUG rtu_framer :115 Frame advanced, resetting header!!
DEBUG context :64 validate: fc-[16] address-2: count-3
DEBUG context :90 setValues[16] 2:3