Modbus TCP float format Big Endian

Hello, I have working modbus configuration but I need to swap double-bytes in float.

  - platform: modbus
    scan_interval: 5
    registers:
    - name: test2
      hub: gmodcnv
      slave: 1
      register: 6
      register_type: input
      data_type: float
      structure: '>f'

I try ‘<f’ and ‘>f’ but without luck.
I probably don’t fully understand https://docs.python.org/3/library/struct.html
When I change data format to int, it give me 17266 = 0x00004372 but I need 0x43720000 (as input for float).

Strange thing: both ‘<f’ and ‘>f’ give me a value 4, but 0x00004372 is 2.4194819285e-41

How can I swap this “double bytes”? ( @pnbruckner can you help me, please? )

Hello, I still don’t know how to change big/little endian, but my problem was, that I need to read 2 registers (2x16bit) to make one (32bit float). Still not depends on ‘<f’ or ‘>f’, but it works…

  - platform: modbus
    scan_interval: 5
    registers:
    - name: test1
      hub: gmodcnv
      slave: 1
      register: 6
      count: 2
      register_type: input
      data_type: float

Not sure if it helps, but for Short I had similar problem

structure: ">2h" # 2 registers in  reversed order should be converted to long

and I solved it with value post processing, like:

        value_template: >-
          {% set valid = not is_state('sensor.A', 'unavailable') %}
          {% set values = states('sensor.A').split(',') %}
          {{ (values[0]|float + (values[1]|float * 255)) / 10 if valid else 'unavailable' }}

Something similar could be done for float:
https://www.h-schmidt.net/FloatConverter/IEEE754.html

(!) If its not supported by original python struct - struct — Interpret bytes as packed binary data — Python 3.9.5 documentation

Note the struct has prefixes - < for little-endian and > for big-endian.

1 Like