1

I have an issue with the pymodbus decoder with strings. For example, when I try to read 'abcdefg' pymodbus gives me 'badcfehg'. The byteorder and the wordorder don't change the result.

Here is my code:

result=client.read_holding_registers(25000,4)
decoder = BinaryPayloadDecoder.fromRegisters(result.registers,byteorder=Endian.Little,wordorder=Endian.Big)
decoder.decode_string(8)

Can someone explain why the order does not change the result? I try with the builder and it's the same problem. However, I don't have this problem with 32 bits floats for example.

I also tried with an older version of pymodbus and it works:

decoder = BinaryPayloadDecoder.fromRegisters(registers,endian=Endian.Little)

Note: I already read the following topic: pymodbus: Issue reading String & multiple type of data from Modbus device but I don't have any access to the modbus server.

Benmo751
  • 53
  • 6
  • 1
    Hello Benmo, by the looks of it you might have found a bug. I think you have three choices: look through the code yourself to see what was changed from the old to the new version, report an issue on [github](https://github.com/riptideio/pymodbus/issues) or stick to the older version. If you decide to look into the code yourself I'll be willing to assist you here if you need help. – Marcos G. Jun 16 '20 at 18:38
  • 1
    The issue is now identified and will be fixed in a future release of Pymodbus: https://github.com/riptideio/pymodbus/issues/508 – Benmo751 Sep 09 '20 at 14:10

2 Answers2

1

The problem is that Modbus specs does not define in what order the two bytes for char strings are sent or even in what order 16-bit words are sent for 32-bit types.

Then some Modbus devices send bytes or words in an order and others do the opposite.

If you are writing a Modbus client then you should add the option in the configuration to be able to invert the order of both bytes and 16-bit words in 32-bit data types.

https://en.wikipedia.org/wiki/Endianness

from56
  • 3,976
  • 2
  • 13
  • 23
  • Thank you for your answer. Yes, that's the aim of the "wordorder" and "byteorder" is not it? When I change the wordorder in the old version of pymodbus, it works (endian=Endian.Big => endian=Endian.Little). However it does not works with the new version of pymodbus. Did I miss something? – Benmo751 Jun 17 '20 at 15:13
  • The explanation may be that the developer of the new version decided to swap Endian.Big with Endian.Little. What I tried to say in my answer is that you should give the user of your software the opportunity to swap Endianness, if the data, whether string or 32 bit, is not read correctly. That is how it is usually done with Modbus drivers because this problem occurs often. – from56 Jun 17 '20 at 18:25
1

I've encountered this same issue with byteorder not working (wordorder seems to be fine). The solution I came up with is to use Struct:

import struct 

Then:

count = 4 #Read 4 16bit registers
    
    result = client.read_holding_registers(25000,count)
    
    for i in range(count):
        result.registers[i] = struct.unpack("<H", struct.pack(">H", result.registers[i]))[0]
    
    decoder = BinaryPayloadDecoder.fromRegisters(result.registers)
    print(decoder.decode_string(7)) #Since string is 7 characters long

This uses Struct to unpack and pack as an unsigned short integer. The endianness does not matter since all you're doing is swapping bytes. The result overwrites the registers so you can then use the BinaryPayloadDecoder as you normally would.

I would have preferred to iterate through the responses instead of using range(count), but couldn't find a way to do it and wanted to post this workaround. If I figure it out, I will let you know.

Dharman
  • 30,962
  • 25
  • 85
  • 135
mattroy10
  • 11
  • 1