Modbus RTU data readback fails in HA

I have an airsource heatpump which provides a Modbus RTU interface.

I can read back the current temperature and the setpoint on the RPI 3b+ using a cheap USB to RS485 dongle from Amazon.

#!/usr/bin/env python3
import minimalmodbus

instrument = minimalmodbus.Instrument('**/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0L482C-if00-port0**', 2, mode = 'rtu', debug = True)  # port name, slave address (in decimal)
instrument.serial.timeout = 1.0

# All register values appear as +1 in the datasheet
#instrument.write_register(3014, 19.8, 1)
htemperature = instrument.read_register(1004, 1)  # Registernumber, number of decimals

setpoint = instrument.read_register(3014, 1)

That results in the following output

MinimalModbus debug mode. Create serial port /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0L482C-if00-port0
MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 02 03 03 EC 00 01 45 88 (8 bytes)
MinimalModbus debug mode. Clearing serial buffers for port /dev/serial/by-id/usb-TDI_FT232R_USB_UART_AB0L482C-if00-port0
MinimalModbus debug mode. No sleep required before write. Time since previous read: 20340262.24 ms, minimum silent period: 2.01 ms.
MinimalModbus debug mode. Response from instrument: 02 03 02 00 C7 BD D6 (7 bytes), roundtrip time: 0.1 ms. Timeout for reading: 1000.0 ms.

MinimalModbus debug mode. Will write to instrument (expecting 7 bytes back): 02 03 0B C6 00 01 66 20 (8 bytes)
MinimalModbus debug mode. Clearing serial buffers for port /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0L482C-if00-port0
MinimalModbus debug mode. Sleeping 0.95 ms before sending. Minimum silent period: 2.01 ms, time since read: 1.05 ms.
MinimalModbus debug mode. Response from instrument: 02 03 02 00 C6 7C 16 (7 bytes), roundtrip time: 0.1 ms. Timeout for reading: 1000.0 ms.

However in HA with the following configuration

default_config:

group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

logger:
        logs:
                homeassistant.components.modbus: notset

modbus:
        name: heating-modbus
        type: serial
        method: rtu
        port: /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0L482C-if00-port0
        baudrate: 9600
        stopbits: 1
        bytesize: 8
        parity: N
        timeout: 2
        climates:
          - name: "Jifon AirGo"
            slave: 2
            address: 1004
            data_type: float16
            max_temp: 25
            min_temp: 15
            precision: 1
            scale: 0.1
            target_temp_register: 3014
            temp_step: 1
            temperature_unit: C

I never read back any data

I’ve confirmed HA is sending data somewhere and that it matches the RTU bytestream in my test application
Note the scripts send 02 03 03 EC 00 01 45 88 (8 bytes) and 02 03 0B C6 00 01 66 20 (8 bytes) which I can see from logs below HA is also sending

2021-10-01 13:44:29 DEBUG (SyncWorker_0) [pymodbus.transaction] Running transaction 3
2021-10-01 13:44:29 DEBUG (SyncWorker_0) [pymodbus.transaction] SEND: 0x2 0x3 0xb 0xc6 0x0 0x1 0x66 0x20
2021-10-01 13:44:29 DEBUG (SyncWorker_0) [pymodbus.framer.rtu_framer] Changing state to IDLE - Last Frame End - None, Current Time stamp - 1633092269.227702
2021-10-01 13:44:29 DEBUG (SyncWorker_0) [pymodbus.client.sync] New Transaction state 'SENDING'
2021-10-01 13:44:29 DEBUG (SyncWorker_0) [pymodbus.transaction] Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'

2021-10-01 13:44:31 DEBUG (SyncWorker_0) [pymodbus.transaction] No response received, Expected 7 bytes Recieved 0 bytes !!!!
2021-10-01 13:44:31 DEBUG (SyncWorker_0) [pymodbus.transaction] Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
2021-10-01 13:44:31 DEBUG (SyncWorker_0) [pymodbus.transaction] RECV:
2021-10-01 13:44:31 DEBUG (SyncWorker_0) [pymodbus.framer.rtu_framer] Frame - [b''] not ready
2021-10-01 13:44:31 DEBUG (SyncWorker_0) [pymodbus.transaction] Getting transaction 2
2021-10-01 13:44:31 DEBUG (SyncWorker_0) [pymodbus.transaction] Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
2021-10-01 13:44:31 DEBUG (SyncWorker_0) [homeassistant.components.modbus.modbus] Pymodbus: heating-modbus: Modbus Error: [Input/Output] No Response received from the remote unit/Unable to decode response
2021-10-01 13:44:31 DEBUG (SyncWorker_3) [pymodbus.transaction] Current transaction state - TRANSACTION_COMPLETE
2021-10-01 13:44:31 DEBUG (SyncWorker_3) [pymodbus.transaction] Running transaction 4
2021-10-01 13:44:31 DEBUG (SyncWorker_3) [pymodbus.transaction] SEND: 0x2 0x3 0x3 0xec 0x0 0x1 0x45 0x88
2021-10-01 13:44:31 DEBUG (SyncWorker_3) [pymodbus.framer.rtu_framer] Changing state to IDLE - Last Frame End - None, Current Time stamp - 1633092271.289393
2021-10-01 13:44:31 DEBUG (SyncWorker_3) [pymodbus.client.sync] New Transaction state 'SENDING'
2021-10-01 13:44:31 DEBUG (SyncWorker_3) [pymodbus.transaction] Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'

HA sends SEND: 0x2 0x3 0xb 0xc6 0x0 0x1 0x66 0x20 and SEND: 0x2 0x3 0x3 0xec 0x0 0x1 0x45 0x88 - which is the same as the byte-stream that works from my test script.

The one thing I can’t prove from these logs is that HA has opened the handle to /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0L482C-if00-port0

I’ve tried some of the work-arounds suggested in this thread Modbus stopped working with rel 2021.7 - #51 by gokuro

particularly

  delay: 5
  close_comm_on_error: false
  retry_on_empty: true
  retries: 10

and while they do prevent HA showing the device as Unavailable - none of those settings appear to enable the response to be received.

Aside from putting another device on the 485 bus - say an Arduino and sniffing the bytes coming out of the PI - is there any way to verify in HA

  • That serial port that it opened
  • That opening the serial port succeeded

I don’t think there is a permissions problem but, as I’m new to HA I’m not sure how - or if - it would be reported in terms of error if HA couldn’t open /dev/ttyUSB0

Anyway I’'d appreciate suggestions on what I’m doing wrong

If there is a permissions issue, it is that the user running the HA process is not part of the “dialout” group, what user is running the HA process, and if it is not root, can you get into a root terminal to enumerate the users of that group?

I believe dockerd is running as root

581 root 20 0 991304 62724 35796 S 1.0 0.8 4:13.96 dockerd

the only other user is “pi” which is in the dialout group

pi@raspberrypi:~/Development/jifon-airgo/examples $ users
pi

pi@raspberrypi:~/Development/jifon-airgo/examples $ groups
pi adm dialout cdrom sudo audio video plugdev games users input netdev gpio i2c spi

fairly sure its not a permission issue

Have you been able to enumerate if /dev/ttyUSB0 exists with the dongle plugged in, and using that for the modbus port?

Yes both /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AB0L482C-if00-port0 and /dev/ttyUSB0 are present

try changing the baud rate to 19200

And also add to main config:

 message_wait_milliseconds: 50