Closed nikito7 closed 2 years ago
How I can use recvPacket?
#!/usr/bin/env python
"""
Pymodbus Synchronous Client Examples
--------------------------------------------------------------------------
The following is an example of how to use the synchronous modbus client
implementation from pymodbus.
It should be noted that the client can also be used with
the guard construct that is available in python 2.5 and up::
with ModbusClient('127.0.0.1') as client:
result = client.read_coils(1,10)
print result
"""
# --------------------------------------------------------------------------- #
# import the various client implementations
# --------------------------------------------------------------------------- #
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
# from pymodbus.client.sync import ModbusUdpClient as ModbusClient
# from pymodbus.client.sync import ModbusSerialClient as ModbusClient
# --------------------------------------------------------------------------- #
# configure the client logging
# --------------------------------------------------------------------------- #
import logging
FORMAT = ('%(asctime)-15s %(threadName)-15s '
'%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
logging.basicConfig(format=FORMAT)
log = logging.getLogger()
log.setLevel(logging.DEBUG)
UNIT = 0x1
def run_sync_client():
# ------------------------------------------------------------------------#
# choose the client you want
# ------------------------------------------------------------------------#
# make sure to start an implementation to hit against. For this
# you can use an existing device, the reference implementation in the tools
# directory, or start a pymodbus server.
#
# If you use the UDP or TCP clients, you can override the framer being used
# to use a custom implementation (say RTU over TCP). By default they use
# the socket framer::
#
# client = ModbusClient('localhost', port=5020, framer=ModbusRtuFramer)
#
# It should be noted that you can supply an ipv4 or an ipv6 host address
# for both the UDP and TCP clients.
#
# There are also other options that can be set on the client that controls
# how transactions are performed. The current ones are:
#
# * retries - Specify how many retries to allow per transaction (default=3)
# * retry_on_empty - Is an empty response a retry (default = False)
# * source_address - Specifies the TCP source address to bind to
# * strict - Applicable only for Modbus RTU clients.
# Adheres to modbus protocol for timing restrictions
# (default = True).
# Setting this to False would disable the inter char timeout
# restriction (t1.5) for Modbus RTU
#
#
# Here is an example of using these options::
#
# client = ModbusClient('localhost', retries=3, retry_on_empty=True)
# ------------------------------------------------------------------------#
from pymodbus.transaction import ModbusRtuFramer
client = ModbusClient('10.1.0.40', port=8888, framer=ModbusRtuFramer, strict=True)
client.connect()
log.debug("Read input registers")
rr = client.read_input_registers(1, 1, unit=UNIT)
assert(not rr.isError()) # test that we are not an error
client.close()
if __name__ == "__main__":
run_sync_client()
Rtuovertcp bridge:
14:40:57.174 TCP: to MCU/1: 010400010001600A
14:40:57.267 TCP: from MCU: 01040C07E50A02060E270E00003C800F6F
Script above:
(venv) user@vbox:~$ ./rtuovertcp.py
2021-10-02 14:40:57,852 MainThread DEBUG sync :215 Connection to Modbus server established. Socket ('10.1.0.51', 36175)
2021-10-02 14:40:57,854 MainThread DEBUG rtuovertcp :75 Read input registers
2021-10-02 14:40:57,855 MainThread DEBUG transaction :139 Current transaction state - IDLE
2021-10-02 14:40:57,855 MainThread DEBUG transaction :144 Running transaction 1
2021-10-02 14:40:57,856 MainThread DEBUG transaction :273 SEND: 0x1 0x4 0x0 0x1 0x0 0x1 0x60 0xa
2021-10-02 14:40:57,857 MainThread DEBUG sync :76 New Transaction state 'SENDING'
2021-10-02 14:40:57,858 MainThread DEBUG transaction :287 Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2021-10-02 14:40:57,979 MainThread DEBUG transaction :375 Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
2021-10-02 14:40:57,980 MainThread DEBUG transaction :297 RECV: 0x1 0x4 0xc 0x7 0xe5 0xa 0x2
2021-10-02 14:40:57,980 MainThread DEBUG rtu_framer :240 Frame - [b'\x01\x04\x0c\x07\xe5\n\x02'] not ready
2021-10-02 14:40:57,981 MainThread DEBUG transaction :465 Getting transaction 1
2021-10-02 14:40:57,981 MainThread DEBUG transaction :224 Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
Traceback (most recent call last):
File "/home/user/./rtuovertcp.py", line 82, in <module>
run_sync_client()
File "/home/user/./rtuovertcp.py", line 77, in run_sync_client
assert(not rr.isError()) # test that we are not an error
AssertionError
Work in TCP
(venv) user@vbox:~$ ./tcp.py
2021-10-02 14:48:16,870 MainThread DEBUG sync :215 Connection to Modbus server established. Socket ('10.1.0.51', 53761)
2021-10-02 14:48:16,871 MainThread DEBUG tcp :80 Read input registers
2021-10-02 14:48:16,872 MainThread DEBUG transaction :139 Current transaction state - IDLE
2021-10-02 14:48:16,873 MainThread DEBUG transaction :144 Running transaction 1
2021-10-02 14:48:16,874 MainThread DEBUG transaction :273 SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0x1 0x4 0x0 0x1 0x0 0x1
2021-10-02 14:48:16,875 MainThread DEBUG sync :76 New Transaction state 'SENDING'
2021-10-02 14:48:16,876 MainThread DEBUG transaction :287 Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2021-10-02 14:48:17,086 MainThread DEBUG transaction :375 Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
2021-10-02 14:48:17,087 MainThread DEBUG transaction :297 RECV: 0x0 0x1 0x0 0x0 0x0 0xf 0x1 0x4 0xc 0x7 0xe5 0xa 0x2 0x6 0xe 0x30 0xf 0xff 0x80 0x0 0x80
2021-10-02 14:48:17,087 MainThread DEBUG socket_framer :147 Processing: 0x0 0x1 0x0 0x0 0x0 0xf 0x1 0x4 0xc 0x7 0xe5 0xa 0x2 0x6 0xe 0x30 0xf 0xff 0x80 0x0 0x80
2021-10-02 14:48:17,088 MainThread DEBUG factory :266 Factory Response[ReadInputRegistersResponse: 4]
2021-10-02 14:48:17,088 MainThread DEBUG transaction :454 Adding transaction 1
2021-10-02 14:48:17,089 MainThread DEBUG transaction :465 Getting transaction 1
2021-10-02 14:48:17,089 MainThread DEBUG transaction :224 Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
Just to be sure, Home assistant modbus integration do not have this problem! @nikito7 have this problem with the modbus configuration because he wants to do something that do not adhere to the modbus standard.
2006 standard!!!
Most implementations had fixes or tweaks for single register 4bytes or more.
My device have uint32 in a single register !!
βmostβ is really grasping for air, lets see some numbers to support your claim ! please do not forget that the modbus organization consist of the biggest modbus companies so if they want it, it would at least be in a draft spec.
Feel free to point at a newer standard where register_size is variable and I will be happy to support your claim.
Some users still use usb rtu
The problem is in rtuframer
4 bytes is non standard, but works with Modbus TCP
2022-03-26 10:36:25 DEBUG (SyncWorker_5) [pymodbus.transaction] Current transaction state - IDLE
2022-03-26 10:36:25 DEBUG (SyncWorker_5) [pymodbus.transaction] Running transaction 1
2022-03-26 10:36:25 DEBUG (SyncWorker_5) [pymodbus.transaction] SEND: 0x1 0x4 0x0 0x28 0x0 0x1 0xb1 0xc2
2022-03-26 10:36:25 DEBUG (SyncWorker_5) [pymodbus.client.sync] New Transaction state 'SENDING'
2022-03-26 10:36:25 DEBUG (SyncWorker_5) [pymodbus.transaction] Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2022-03-26 10:36:25 DEBUG (SyncWorker_5) [pymodbus.transaction] Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
2022-03-26 10:36:25 DEBUG (SyncWorker_5) [pymodbus.transaction] RECV: 0x1 0x4 0x4 0x0 0x4b 0xa0 0xd7
2022-03-26 10:36:25 DEBUG (SyncWorker_5) [pymodbus.framer.rtu_framer] Frame - [b'\x01\x04\x04\x00K\xa0\xd7'] not ready
2022-03-26 10:36:25 DEBUG (SyncWorker_5) [pymodbus.transaction] Getting transaction 1
2022-03-26 10:36:25 DEBUG (SyncWorker_5) [pymodbus.transaction] Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
RECV: 0x1 0x4 0x4 0x0 0x4b 0xa0 0xd7
pymodbus.framer.rtu_framer] Frame - [b'\x01\x04\x04\x00K\xa0\xd7'] not ready
This is strange
x00K?
your system delivers an incomplete frame.
Only misses CRC but it's normal in pymodbus I think
RECV is correct without crc.
Framer processing not
I suppose that is hardcoded 2 bytes
But it works in Modbus TCP....
Should be easy to fix, but I don't understand the code π
@nikito7 I do not understand this
Only misses CRC but it's normal in pymodbus I think
RECV is correct without crc. and I suppose that is hardcoded 2 bytes
What exactly are we talking about here ? The CRC is calculated and a missing CRC is considered as an invalid frame. You can try add some more delay to see if all the bytes are received.
Makes sense. It's this?
How dynamically configure?
# * strict - Applicable only for Modbus RTU clients.
# Adheres to modbus protocol for timing restrictions
# (default = True).
# Setting this to False would disable the inter char timeout
# restriction (t1.5) for Modbus RTU
Maybe need change code?
Because pymodbus will expect only a two bytes register data...
Anyway
Modbus TCP don't have CRC. How pymodbus known the number of bytes to read?
Because all work. Even a special 12 bytes register...
So RTU will need some dynamically expected size...
Forgetting big anormal registers. I only want try to read a single 32bits register (4 bytes)
Modpoll for example have a option for it:
Use Daniel/Enron single register 32-bit mode
@janiversen
Just to be sure, Home assistant modbus integration do not have this problem! @nikito7 have this problem with the modbus configuration because he wants to do something that do not adhere to the modbus standard.
Tell it to all EDP clients in Portugal. π
Tasmota work. ESPHome work. Modpoll work. Home Assistant (TCP) work.
Why shouldn't pymodbus RTU support 32bits too...
because it is non-standard and if tcp works then you have a solution. If you want a non-standard solution the best way is to fork this repo and make your changes locally.
btw this is not a question of crc, it is simply your device sends an unexpected structure (1 register is 4 bytes not 2).
@nikito7 it is good to have and I am willing to accept any PR's if you are willing to work on it. This is something not really required by the majority of the users and being the only developer who is working on this project at my free time, it is quite difficult to accomodate this feature request with so many items pending in the backlog.
(pymodbus) D:\[ssn]\[dev]\pymodbus>py rtu.py
2022-03-29 05:39:12,667 MainThread DEBUG sync :215 Connection to Modbus server established. Socket ('10.1.0.71', 54760)
2022-03-29 05:39:12,667 MainThread DEBUG rtu :75 Read input registers
2022-03-29 05:39:12,669 MainThread DEBUG transaction :139 Current transaction state - IDLE
2022-03-29 05:39:12,670 MainThread DEBUG transaction :144 Running transaction 1
2022-03-29 05:39:12,671 MainThread DEBUG transaction :273 SEND: 0x1 0x4 0x0 0x1 0x0 0x1 0x60 0xa
2022-03-29 05:39:12,672 MainThread DEBUG sync :76 New Transaction state 'SENDING'
2022-03-29 05:39:12,673 MainThread DEBUG transaction :287 Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
2022-03-29 05:39:12,788 MainThread DEBUG transaction :375 Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
2022-03-29 05:39:12,789 MainThread DEBUG transaction :297 RECV: 0x1 0x4 0xc 0x7 0xe6 0x3 0x1d 0x2 0x5 0x27 0x9 0x0 0x0 0x3c 0x80 0x52 0xc7
2022-03-29 05:39:12,791 MainThread DEBUG rtu_framer :185 Getting Frame - 0x4 0xc 0x7 0xe6 0x3 0x1d 0x2 0x5 0x27 0x9 0x0 0x0 0x3c 0x80
2022-03-29 05:39:12,792 MainThread DEBUG factory :266 Factory Response[ReadInputRegistersResponse: 4]
2022-03-29 05:39:12,793 MainThread DEBUG rtu_framer :107 Frame advanced, resetting header!!
2022-03-29 05:39:12,793 MainThread DEBUG transaction :454 Adding transaction 1
2022-03-29 05:39:12,794 MainThread DEBUG transaction :465 Getting transaction 1
2022-03-29 05:39:12,795 MainThread DEBUG transaction :224 Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
Not really a solution but worked. Make that dynamic will be hard. And maybe not the correct code to change π
Just a test anyway Single 12 bytes register: clock/date
I've just hit exactly this problem as I was using pymodbus via https://github.com/gavinying/modpoll. I've been reading about this issue and it looks like Enron or Enron/Daniels Modbus is standard modbus with a few vendor extensions.
I see that @rahulraghu94 published his Daniel/Enron Modbus work under https://github.com/u9n/enron-modbus if anyone's interested, although it would be great to see this incorporated under pymodbus especially because of the ripple effect through Home Assistant and so other many open source projects that rely on this library.
Versions
Pymodbus Specific
Description
With Modbus TCP registers above 2 bytes work correctly.
My device have single registers with N bytes. Like clock, serial number (count:1; variable size)
But in RTU or rtuovertcp still fails.
Maybe a CRC issue?
Code and Logs