core: RFXTRX integration doesn't recover from a dropped network connection to an RFXTRX, requires HA restart

The problem

I have an RFXTRX433 device, connected to Home Assistant via a tcp connection.

This works well in normal operation. However, if the TCP connection is interrupted due to a network issue (e.g. RFXTRX is at a remote location and broadband is interrupted), then Home Assistant loses connection to it. This state can’t currently be recovered from when the network connection is restored without restarting the whole of Home Assistant.

I suggest one of the following is considered:

  1. The RFXTRX integration with Home Assistant monitors the health of the TCP connection to the RFXTRX, and if it drops, attempts to restart it on a timer
  2. The RFXTRX integration exposes a rfxtrx.reconnect service which can be called by an automation (for example, one could detect a lack of rfxtrx events and use this to trigger the reconnect service)

Environment

  • Home Assistant Core release with the issue: 0.114.1
  • Last working Home Assistant Core release (if known): N/A
  • Operating environment (OS/Container/Supervised/Core): HassOS 4.12
  • Integration causing this issue: RFXTRX
  • Link to integration documentation on our website: https://www.home-assistant.io/integrations/rfxtrx/

Problem-relevant configuration.yaml

rfxtrx:
  host: !secret rfxtrx_ip
  port: 2167
  automatic_add: true

Traceback/Error logs


Additional information

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 6
  • Comments: 33 (8 by maintainers)

Most upvoted comments

Hi again, after some days I had some issue because of network interruptions. So I research on how to keep the socat client re-trying to connect event if the server side is restarted. I came to not use ser2net on the server side (where the USB device is hosted), but to use socat too. This time as TCP server. I also added some parameters to the socat client to keep retrying to connect and also on HA restart to kill any previous socat client connection.

Now I have in the HA configuration the following shell command executed on any start or restart:

shell_command:
  ttyrfxcom: pkill socat && sleep 5 && (socat pty,link=/dev/ttyRFXCOM,b38400,raw,echo=0,user=root,group=uucp,mode=777 tcp:192.168.1.123:5123,forever,interval=10,fork,keepalive,keepidle=10,keepintvl=10,keepcnt=100) &

and on USB host, I removed ser2net and replaced by the the following socat command: socat -ls -d -d FILE:/dev/ttyUSB1,b38400,raw,echo=0,ignoreeof TCP-LISTEN:5123,reuseaddr

furthermore it is possible to run the socat TCP server as docker container by using the alpine/socat docker image. Here my docker-compose.yml file:

version: "3.8"
services:
  rfxcom2ethernet:
    image: alpine/socat
    container_name: rfxcom2ethernet
    command: "-ls -d -d FILE:/dev/ttyUSB1,b38400,raw,echo=0,ignoreeof TCP-LISTEN:5123,reuseaddr"
    ports:
      - "5123:5123"
    restart: unless-stopped
    devices:
      - "/dev/ttyUSB1:/dev/ttyUSB1"

then start that container with: docker-compose up -d

Now it is possible to restart the USB host or reboot HA via the app or the HA container in case is runs as docker container. In each use case, the end-to-end connection between the emulated USB RFXCOM device in HA and the physical USB device is rebuilt over the TCP bridge.

Hope this might help somebody.

Still a valid issue for me. Even reload does not work for me.

When sending a command to my cover:

  File "/usr/src/homeassistant/homeassistant/components/rfxtrx/cover.py", line 124, in async_open_cover
    await self._async_send(self._device.send_up2sec)
  File "/usr/src/homeassistant/homeassistant/components/rfxtrx/__init__.py", line 516, in _async_send
    await self.hass.async_add_executor_job(fun, rfx_object.transport, *args)
  File "/usr/local/lib/python3.9/concurrent/futures/thread.py", line 52, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/local/lib/python3.9/site-packages/RFXtrx/__init__.py", line 162, in send_up2sec
    self.send_command(transport, 0x11)
  File "/usr/local/lib/python3.9/site-packages/RFXtrx/__init__.py", line 130, in send_command
    transport.send(pkt.data)
  File "/usr/local/lib/python3.9/site-packages/RFXtrx/__init__.py", line 794, in send
    self.sock.send(pkt)
BrokenPipeError: [Errno 32] Broken pipe

Still valid

My RFXCOM is just standing there, doing nothing, waiting for this fix to be actually used.

Update: after updating to HA version 2023.4.1, it seems that chaining commands in the shell_command (with &&) doesn’t work anymore? My current workaround is: splitting each command in single shell_command and call each shell_command one after the other in the automation action list (triggered on HA startup).

shell_command:
  ttyrfxcom_kill: pkill socat
  ttyrfxcom_create: (socat pty,link=/dev/ttyRFXCOM,b38400,raw,echo=0,user=root,group=uucp,mode=777 tcp:192.168.1.123:5123,forever,interval=10,keepalive,keepidle=10,keepintvl=10,keepcnt=100) &

automation:
- alias: open_rfxcom_serial_port
  trigger:
    platform: homeassistant
    event: start
  action:
    - service: shell_command.ttyrfxcom_kill
    - service: shell_command.ttyrfxcom_create
    - service: homeassistant.reload_config_entry
      target:
        device_id: 988fa84a9abad15adb8bac568ef7367c

Hi, I had the same issue using a RFX433 connected on USB and piped over ethernet with ser2net running on the USB host. After some hours HA losts the connection with “broken pipe” error and only restarting HA temporarily solved the issue.

After some investigation I assume that the RFXCOM integration with network connection might not work well with ser2net in HA.

There exists another client side tool named socat that can be used to delegate the ser2net socket communication to socat instead of HA and exposing/emulating a serial port to HA. I found that idea from here.

That way HA is (should) not aware of the network connection and we can connect the RFXCOM device over serial port while the physical serial USB port is connected on the remote network host.

On the HA host we can run the following command to expose an emulate serial port connected to the ser2net USB device: (socat pty,link=/dev/ttyRFXCOM,b38400,raw,echo=0,user=root,group=uucp,mode=777 tcp:<your ser2net ip>:<your ser2net port>) & This will create the /dev/ttyRFXCOM serial port on the HA host. Now we can remove any previously added RFXCOM device/integration from HA and add it again by connecting it over serial port /dev/ttyRFXCOM instead of network connection.

That works great but the story doesn’t stop here. Since I’m running HA in a docker container I wanted to run that socat command inside the container on startup (luckily socat is already installed in the HA docker image). First I tried to add the command entry in my docker-compose file like the following:

services:
    homeassistant:    
    image: "ghcr.io/home-assistant/home-assistant:stable"    
    [...]  
    command: sh -c '(socat pty,link=/dev/ttyRFXCOM,b38400,raw,echo=0,user=root,group=uucp,mode=777 tcp:192.168.1.123:5123) &'

and hoping that this command runs in the background before HA starts. But, for a reason I didn’t yet figured out, this command prevents HA to start…

So I ended up with some workaround: I didn’t create the socat serial port from my docker-compose but let HA execute that command itself on startup event. First I added a shell_command in my configuration.yaml file:

shell_command:
  ttyrfxcom: (socat pty,link=/dev/ttyRFXCOM,b38400,raw,echo=0,user=root,group=uucp,mode=777 tcp:192.168.1.123:5123) &

Then I added an automation in my configuration.yaml file:

automation:
   - alias: open_rfxcom_serial_port
     trigger:
       platform: homeassistant
       event: start
     action:
       - service: shell_command.ttyrfxcom
       - service: homeassistant.reload_config_entry
         target:
           device_id: 988fa84a9abad15adb8bac568ef7367c

this last automation, is triggered on HA startup and run the previously defined shell_command and also reloads the RFXCOM device integration by calling the homeassistant.reload_config_entry service.

Now when my HA docker container starts, of course some timeout errors in log appears saying the serial port for the RFXCOM device is not available. But a few seconds later HA is executing the automation by making the remote serial port available and reloads the RFXCOM device integration successfully.

Now by delegating the remote serial port communication to socat, I hope that the HA RFXCOM virtually connected over network will be stable and reliable.

I can have a look but I’m a scala developer and my Python skills are a bit rusty.

I’m guessing the most important thing right now is being able to detect/catch the broken pipe errors and then recovering/reconnecting, right?

My HA and rfxcom module are setup on the same pi, but I was having issues with the USB connection as well. Also after x days it would stop working and giving timeouts. Only a restart of the system/ha would fix things.

That’s why I thought, let’s run ser2net in docker to avoid usb connection issues. Unfortunately, it seems network connection has sort of the same issues.

This requires a rework of rfxtrx library. Which is somewhat unmaintained. So needs somebody to step up and fix it.

There hasn’t been any activity on this issue recently. Due to the high number of incoming GitHub notifications, we have to clean some of the old issues, as many of them have already been resolved with the latest updates. Please make sure to update to the latest Home Assistant version and check if that solves the issue. Let us know if that works for you by adding a comment 👍 This issue has now been marked as stale and will be closed if no further activity occurs. Thank you for your contributions.