|
decoded = decoded[len(decoded)-objects_count:] |
for coils decoded data, this line of code will fetch the trailing items rather than the leading items. It results in wrong data.
I tried following code to verify the logic:
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
if __name__ == '__main__':
objects_count = 2
byte_order = Endian.LITTLE
word_order = Endian.BIG
# mock coils data
encoded_data = [True, False, False, False, False, False, False, False]
decoder = BinaryPayloadDecoder.fromCoils(encoded_data, byteorder=byte_order, _wordorder=word_order)
decoded = decoder.decode_bits()
decoded_lastbyte = decoder.decode_bits()
decoded += decoded_lastbyte
decoded = decoded[len(decoded) - objects_count:]
print('result: ', decoded) # it prints [False, True], not [True, False]
after investigating, this issue is caused by the reverse of bits in the BinaryPayloadDecoder.fromCoils().
By design, the original bits in ReadCoilsResponse is in the same order as the actual coils. when creating decoder, the code is supposed to pack the bits to bytes in the reversed order and at last at decoding stage, read the bits back reversely again. so first right order(response bits) -> reverse order(decoder packing) -> reversed reverse order = right order(decode) will return correct result. However, in the BinaryPayloadDecoder.fromCoils() method, it reverses the original coils bits prior to packing it into bytes. So the processing sequence become: original bits(coils bits) -> reversed bits(from coils) -> reversed reversed bits = original bits(packing) -> reversed bits(decode). And then, the code fetches the bits from beginning, resulting incorrectly bit value:
if lower_type in ['bit', 'bits']:
decoded = decoder_functions[lower_type]()
decoded_lastbyte = decoder_functions[lower_type]()
decoded += decoded_lastbyte
decoded = decoded[len(decoded)-objects_count:]
thingsboard-gateway/thingsboard_gateway/connectors/modbus/bytes_modbus_uplink_converter.py
Line 284 in bbede93
for coils decoded data, this line of code will fetch the trailing items rather than the leading items. It results in wrong data.
I tried following code to verify the logic:
after investigating, this issue is caused by the reverse of bits in the BinaryPayloadDecoder.fromCoils().
By design, the original bits in ReadCoilsResponse is in the same order as the actual coils. when creating decoder, the code is supposed to pack the bits to bytes in the reversed order and at last at decoding stage, read the bits back reversely again. so first right order(response bits) -> reverse order(decoder packing) -> reversed reverse order = right order(decode) will return correct result. However, in the BinaryPayloadDecoder.fromCoils() method, it reverses the original coils bits prior to packing it into bytes. So the processing sequence become: original bits(coils bits) -> reversed bits(from coils) -> reversed reversed bits = original bits(packing) -> reversed bits(decode). And then, the code fetches the bits from beginning, resulting incorrectly bit value: