Quantcast
Channel: Configuration - Home Assistant Community
Viewing all articles
Browse latest Browse all 95370

ZHA - Reconnect mechanism for USB Dongles

$
0
0

@perryflynn wrote:

Hi,

I am working on a reliable connection of my Zigbee Dongle (Conbee II) to Home Assistant Core which is running as Docker Container. I am using usbip to bring the Zigbee Dongle from a Raspberry Pi to my Docker Server.

On the Raspberry Pi I have already a reboot-safe and hotplug-stable solution. Here the implementation steps as Ansible Playbook:

---

# root@dashboard:/etc/systemd/system# lsusb -d 1cf1:0030 -v

# Bus 001 Device 011: ID 1cf1:0030 Dresden Elektronik
# Device Descriptor:
#   bLength                18
#   bDescriptorType         1
#   bcdUSB               2.01
#   bDeviceClass            2 Communications
#   bDeviceSubClass         0
#   bDeviceProtocol         0
#   bMaxPacketSize0        64
#   idVendor           0x1cf1 Dresden Elektronik
#   idProduct          0x0030
#   bcdDevice            1.00
#   iManufacturer           1 dresden elektronik ingenieurtechnik GmbH
#   iProduct                2 ConBee II
#   iSerial                 3 DE2154525
#   bNumConfigurations      1


#
# -> Zigbee Host
#

- name: Setup usbip on Zigbee Stick Host
  hosts:
    - dashboard

  vars:
    usbvendorid: "1cf1"
    usbproductid: "0030"

  tasks:

    - name: Install usbip
      package:
        name: usbip
        state: present

    - name: Load kernel modules at boot
      copy:
        dest: /etc/modules-load.d/usbipd.conf
        owner: root
        group: root
        mode: u=rw,go=r
        content: |
          # load kernel modules needed for usbip daemon
          # this file is managed by ansible

          usbip_host

    - name: Load kernel modules now
      modprobe:
        name: usbip_host
        state: present

    - name: "Create vendor:product bind script for usbip"
      copy:
        dest: /usr/sbin/usbip-bind-vendorproduct
        owner: root
        group: root
        mode: u=rwx,go=r
        content: |
          #!/bin/bash

          VENDORPRODUCT=$(echo "$1" | sed 's/-/:/g')
          MODE=$2
          BUSID=$(usbip list -l | grep -oP "busid\s+([0-9\-\.]+)\s+\(${VENDORPRODUCT}\)" | head -n 1 | awk '{print $2}')
          USBIPACTIVE=$(pidof usbipd 2>&1 > /dev/null; echo $?)

          if [ $USBIPACTIVE -ne 0 ]; then
              echo "usbip daemon is not running"
              exit 1
          fi

          if [ "$MODE" == "bind" ]; then
              /usr/sbin/usbip bind -b $BUSID
          elif [ "$MODE" == "unbind" ]; then
              /usr/sbin/usbip unbind -b $BUSID
          else
              echo "Unknown Mode"
              exit 1
          fi

    - name: Create systemd unit for the zigbee stick
      copy:
        dest: /etc/systemd/system/usbip-device@.service
        owner: root
        group: root
        mode: u=rw,go=r
        content: |
          [Unit]
          Description=USB/IP Binding on %I
          After=network-online.target usbipd.service
          Wants=network-online.target
          Requires=usbipd.service

          [Service]
          Type=simple
          ExecStart=/usr/sbin/usbip-bind-vendorproduct %i bind
          RemainAfterExit=yes
          ExecStop=/usr/sbin/usbip-bind-vendorproduct %i unbind
          Restart=on-failure

          [Install]
          WantedBy=multi-user.target

    - name: Create systemd unit for usbip
      copy:
        dest: /etc/systemd/system/usbipd.service
        owner: root
        group: root
        mode: u=rw,go=r
        content: |
          [Unit]
          Description=USB/IP server
          After=network.target

          [Service]
          ExecStart=/usr/sbin/usbipd

          [Install]
          WantedBy=multi-user.target

    - name: Enable and start usbip dongle
      systemd:
        daemon_reload: yes
        enabled: yes
        name: "usbip-device@{{usbvendorid}}-{{usbproductid}}"

    - name: Enable and start usbipd service
      systemd:
        daemon_reload: yes
        enabled: yes
        name: usbipd
        state: started

    - name: Create udev hotplug trigger script
      copy:
        dest: /usr/sbin/usbip-hotplug-trigger
        owner: root
        group: root
        mode: u=rwx,go=r
        content: |
          #!/bin/bash

          /usr/sbin/usbip-bind-vendorproduct ${ID_VENDOR_ID}:${ID_MODEL_ID} bind

    - name: Create udev rule for hotplug dongle
      copy:
        dest: /etc/udev/rules.d/usbip.rules
        owner: root
        group: root
        mode: u=rw,go=r
        content: |
          ACTION=="add", ATTR{idVendor}=="{{usbvendorid}}", ATTR{idProduct}=="{{usbproductid}}", RUN+="/usr/sbin/usbip-hotplug-trigger"
      register: dongleudevrule

    - name: Restart udev
      service:
        name: udev
        state: restarted
      when: dongleudevrule.changed

Now the problem: The implementation of the communication between the usb device and hass is not reconnect-safe. If there is any issue with the communication between, the container needs to be restarted.

I am able to bring the usb device into the container with cgroup rules, so that I can hotplug:

docker create \
    --init \
    --name "hass" \
    --hostname hass \
    --network hassinternal \
    --device-cgroup-rule='c 166:0 rmw' \
    -v /containerdata/homeassistant:/config \
    -v /etc/localtime:/etc/localtime:ro \
    homeassistant/home-assistant:latest

Now I can start the container and add the device right afterwards. (If this works without any issues, I would create an extension of the container image and to the creation of the usb device via startup script.)

usbip attach -r dashboard -b 1-1.4
docker start hass
docker exec hass mknod /dev/ttyACM0 c 166 0

Until this point, it works without any problems. But if I detach the device or if there is a network issue, hass throws an exception and the implementation is broken until I restart the container:

2020-04-05 09:58:14 WARNING (MainThread) [zigpy_deconz.api] No response to 'Command.write_parameter' command
2020-04-05 09:58:14 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/zigpy_deconz/zigbee/application.py", line 36, in _reset_watchdog
    await self._api.write_parameter(NetworkParameter.watchdog_ttl, 3600)
  File "/usr/local/lib/python3.7/site-packages/zigpy_deconz/api.py", line 210, in _command
    return await asyncio.wait_for(fut, timeout=COMMAND_TIMEOUT)
  File "/usr/local/lib/python3.7/asyncio/tasks.py", line 449, in wait_for
    raise futures.TimeoutError()
concurrent.futures._base.TimeoutError
2020-04-05 09:58:49 WARNING (MainThread) [zigpy_deconz.api] No response to 'Command.aps_data_request' command

Is there any way to make this more stable?

It would be awesome to have an reconnect mechanism in hass. I’ve already looked into the code, but my python skills are not strong enough.

Kind Regards
Christian

Posts: 1

Participants: 1

Read full topic


Viewing all articles
Browse latest Browse all 95370

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>