Проблема декодирования строки Python Modbus

У меня проблема со строками в декодере pymodbus. Например, когда я пытаюсь прочитать abcdefg, pymodbus выдает мне badcfehg. Byteorder и wordorder не меняют результат.

Вот мой код:

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

Может кто-нибудь объяснить, почему порядок не меняет результат? Пробую со строительом, та же проблема. Однако у меня нет этой проблемы, например, с 32-битными числами с плавающей запятой.

Я также пробовал использовать более старую версию pymodbus, и она работает:

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

Примечание. Я уже читал следующую тему: pymodbus : Проблема с чтением строки и нескольких типов данных с устройства Modbus, но у меня нет доступа к серверу Modbus.


person Benmo751    schedule 16.06.2020    source источник
comment
Привет, Бенмо, судя по всему, ты мог найти ошибку. Я думаю, у вас есть три варианта: просмотреть код самостоятельно, чтобы увидеть, что было изменено со старой версии на новую, сообщить о проблеме на github или придерживайтесь более старой версии. Если вы решите самостоятельно изучить код, я буду рад помочь вам здесь, если вам понадобится помощь.   -  person Marcos G.    schedule 16.06.2020
comment
Теперь проблема выявлена ​​и будет исправлена ​​в следующем выпуске Pymodbus: github.com/riptideio/ pymodbus / issues / 508   -  person Benmo751    schedule 09.09.2020


Ответы (2)


Проблема в том, что спецификации Modbus не определяют, в каком порядке отправляются два байта для символьных строк или даже в каком порядке отправляются 16-битные слова для 32-битных типов.

Затем некоторые устройства Modbus отправляют байты или слова в определенном порядке, а другие - наоборот.

Если вы пишете клиент Modbus, вам следует добавить параметр в конфигурацию, чтобы иметь возможность инвертировать порядок байтов и 16-битных слов в 32-битных типах данных.

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

person Lluis Felisart    schedule 16.06.2020
comment
Спасибо за ваш ответ. Да, это цель wordorder и byteorder, не так ли? Когда я меняю порядок слов в старой версии pymodbus, он работает (endian = Endian.Big = ›endian = Endian.Little). Однако это не работает с новой версией pymodbus. Я что-то пропустил? - person Benmo751; 17.06.2020
comment
Объяснение может заключаться в том, что разработчик новой версии решил заменить Endian.Big на Endian.Little. В своем ответе я попытался сказать, что вы должны дать пользователю вашего программного обеспечения возможность менять порядок байтов, если данные, будь то строковые или 32-битные, читаются неправильно. Именно так обычно и поступают с драйверами Modbus, потому что эта проблема возникает часто. - person Lluis Felisart; 17.06.2020

Я столкнулся с этой же проблемой с неработающим byteorder (wordorder, похоже, в порядке). Решение, которое я придумал, - использовать Struct:

import struct 

Потом:

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

Это использует Struct для распаковки и упаковки в виде короткого целого числа без знака. Порядок байтов не имеет значения, поскольку все, что вы делаете, это меняете местами байты. В результате регистры перезаписываются, поэтому вы можете использовать BinaryPayloadDecoder, как обычно.

Я бы предпочел перебирать ответы вместо использования диапазона (счетчика), но не смог найти способ сделать это и хотел опубликовать этот обходной путь. Если разберусь, дам тебе знать.

person mattroy10    schedule 08.09.2020