I stated the PLC data appeared to be in hexadecimal and the conversion from hex to decimal was the right number. Scaling would not work in that case I would assume. Maybe to move the decimal. I am interested but your not giving me much to work with here. I am not a YAML coder. Default imperial.
I’m a volunteer like everyone else here who offers assistance. In fact, I don’t even use the Modbus integration but read its documentation in order to help you. However, I do agree that using scale alone probably won’t produce the result you want. That’s why I am leaving the discussion and hopefully someone with far more Modbus experience will help you.
Blockquote
I’m a volunteer like everyone else here who offers assistance.
I understand. There are also people that don’t know where to look for the answers to the questions you are asking, like myself. I had to dig around.
Thanks for trying anyway.
FWIW, you might want to investigate the structure option. Unfortunately, there’s only one example of its usage in the documentation but it seems to suggest that you can indicate the data’s type. Sorry I can’t be of more help.
I searched the forum for “Modbus structure” and found this example:
data_type: custom
structure: ">1f"
However, you might also need to use the precision option to specify the number of decimal places. Here’s the source of the information (maybe its author can help you):
Not clue about the modbus hex/dec mismatch, but here is a crude way to go back from 1909 (i.e. 0x775) to 775:
Tested in template debugger.
{% set hex = 1909 %}
{% set m = hex // 4096 %}
{% set hex = hex - m *4096 %}
{% set c = hex // 256 %}
{% set hex = hex - c *256 %}
{% set d = hex // 16 %}
{% set u = hex - d *16 %}
{{ m*1000 + c*100 + d*10 + u }}
If you prepend 0x to an integer, the Jinja2 interpreter understands how to convert it to decimal.
You can’t add it to the Modbus configuration. You would have to create a Template Sensor to convert the value of sensor.temp1 to display the desired value. However, none of that is needed if you can get data_type and structure configured correctly.
I don’t think it’s a matter of format. An int is an int, ie.a bunch of bits at the end of the day. You can display it in base 2, 10 or 16, it’s still the same value.
There is likely a logic error somewhere, maybe in the PLC, that did a wrong conversion.
My reply was in reference to the example you posted containing several lines of calculations in Jinja2. It isn’t necessary to use all of that to make the Jinja2 interpreter convert a hex value into decimal (it just needs a hint that the value is hexadecimal).
As for the Modbus sensor, based on reading related posts, it’s not uncommon to receive hex values that must be converted to decimal. The solution lies in the correct use of the available options (notably data_type and structure) but I can’t experiment with them because I don’t have anything based on Modbus. It should not be necessary to employ a Template Sensor to perform the conversion.
If the sensor reports 775, this prepends 0x to ensure it’s understood to be a hex value and then converted to an integer but informing the int function that it’s dealing with a base 16 (hex) value.
Thanks for mentioning my post. Looking at initial question and my configs I found similar sensor in my network - there is no need to convert it in jinja or with math function as modbus already does it.
If you look in to the source then you’ll find out that its actually straight call to the ‘struct’ Python function. Its actually powerful and compact utility function to work with network data. Take a look at documentation - struct — Interpret bytes as packed binary data — Python 3.9.6 documentation
Not sure why Jan or someone who contributes to the modbus module did not put a link to the functions in HA documentation.
Then you have converted value without decimal that I validate and divide by 10 in a template value:
foo_v:
friendly_name: Foo Voltage
value_template: >-
{% set valid = not is_state('sensor.hex_sensor', 'unavailable') %}
{% set values = states('sensor.hex_sensor').split(',') %}
{{ (values[0]|float / 10) if valid else 'unavailable' }}
icon_template: mdi:sine-wave
unit_of_measurement: V
This approach is also good for debug - when you see wrong data you can dig in to original value received by modbus before conversion. And for the end user you have nice value from template.
I usually keep separate hidden tab with all values from RS485 network. This help to identify RS485 problems by network segment.
Sorry, but I don’t think struct would help here.
It is used for unpacking C structs. You seem to be reading 2 registers and interpreting that as 2 short integers.
$ python3
Python 3.8.10 (default, Jun 2 2021, 10:49:15)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
+ >>> import struct
+ >>> struct.unpack(">2h", b'\x00\x03\x01\x01')
(3, 257)
Unless I’m missing something, this won’t help us convert the number to hex.