home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
71.11k stars 29.79k forks source link

modbus error while using negative numbers for writing to an int16 register #117481

Closed Frantik85 closed 3 months ago

Frantik85 commented 3 months ago

The problem

I think I may have found a bug, though I am not sure - that's why I am here ;)

Situation:

used modbus configuration (excerpt):

modbus:
  - name: proxon
    type: serial
    delay: 5
    baudrate: 19200
    bytesize: 8
    method: rtu
    parity: E
    port: /dev/serial/by-id/usb-1a86_USB2.0-Ser_-if00-port0
    stopbits: 1
    sensors:
      name: "Offsettemperatur NBP Room 1"
            unique_id: proxon_offsettemperatur_nbp_room_1
            scan_interval: 30
            slave: 41
            address: 213
            input_type: holding
            unit_of_measurement: °C
            data_type: int16

the script used:

service: modbus.write_register
            data:
              address: 213
              slave: 41
              hub: proxon
              value: |-{% if offset is defined %}{{ offset}}{% else %}{{0}}{% endif %}

The error I get when I pass in negative values to this script: value must be at least 0 @ data['value'][0]

If you have further questions, please let me know!

What version of Home Assistant Core has the issue?

core-2024.5.2

What was the last working version of Home Assistant Core?

No response

What type of installation are you running?

Home Assistant OS

Integration causing the issue

No response

Link to integration documentation on our website

No response

Diagnostics information

No response

Example YAML snippet

- service: modbus.write_register
   data:
    address: 233
    slave: 41
    hub: proxon
    value: -3

Anything in the logs that might be useful for us?

# This protocol entry was created when I tried the example snippet provided within this ticket in the developer tool -> services:
------------------------------------------------------------------
Logger: homeassistant.helpers.script.websocket_api_script
Quelle: helpers/script.py:1934
Erstmals aufgetreten: 14. Mai 2024 um 21:22:00 (23 Vorkommnisse)
Zuletzt protokolliert: 14. Mai 2024 um 23:00:52

websocket_api script: Error executing script. Invalid data for call_service at pos 1: value must be at least 0 @ data['value'][0]

Additional information

No response

home-assistant[bot] commented 3 months ago

Hey there @janiversen, mind taking a look at this issue as it has been labeled with an integration (modbus) you are listed as a code owner for? Thanks!

Code owner commands Code owners of `modbus` can trigger bot actions by commenting: - `@home-assistant close` Closes the issue. - `@home-assistant rename Awesome new title` Renames the issue. - `@home-assistant reopen` Reopen the issue. - `@home-assistant unassign modbus` Removes the current integration label and assignees on the issue, add the integration domain after the command. - `@home-assistant add-label needs-more-information` Add a label (needs-more-information, problem in dependency, problem in custom component) to the issue. - `@home-assistant remove-label needs-more-information` Remove a label (needs-more-information, problem in dependency, problem in custom component) on the issue.

(message by CodeOwnersMention)


modbus documentation modbus source (message by IssueLinks)

janiversen commented 3 months ago

That is not a bug, the service write to a register which is defined as 16bit which eguals UINT16, so it does not know how to convert a negative value.

Frantik85 commented 3 months ago

Hey @janiversen , I am confused - in the communication matrix of the modbus in my heating it is clearly stated that it can use negative numbers. Also, int16 is not uint16 AFAIK or do you mean, that the modbus integration itself is only able to work with UINT16 internally?

janiversen commented 3 months ago

A device typically interpret registers, e.g, many devices combine 2 registers to have a INT32 or UINT32, but that is a device definition. The modbus protocol defines a register as 16bit and not as int16 or uint16, and for that reason the service expects a UINT16.

janiversen commented 3 months ago

The UINT16 was chosen because it is really 16bit. The integration and lib uses bytes internally, but that is difficult to handle in HA.

If you like the service to work differently Pull Requests are welcome, but please remember if you move away from writing a register users will expect support for int/float/string of different lengths 16/32/64.

Frantik85 commented 3 months ago

hm, alright, understood. So I might work around this by converting my negativ numbers to the corresponding positive integer numbers. Say I want to apply an offset of "-1" this will result in a binary value: 65535 --> just tested this, and it worked. ^^ To be fair - this behavior is nevertheless unexpected ;)

Thx for your comment and help! I could dive into the code and see if I could work my way through to support signed integers too.

janiversen commented 3 months ago

Not sure how this can be unexpected, the documentation states

(write_register) A single value or an array of 16-bit values. Single value will call modbus function code 0x06. Array will call modbus function code 0x10. Values might need reverse ordering.

nothing about int16.