HA Docker with OTBR docker

I have a SkyConnect flashed with thread only. Is this still unusable with HA docker? I’d like to get a thread network up and running and try out some new devices, but I don’t want to migrate everything to HAOS.

Could you add some context to the issue you mention, please.
I personally have no clue of what you’re talking about…

Using skyconnect as a thread border router while running home assistant in a docker container.

I got that. What I have not context over is the “still unusable” part.

Without that context, I don’t get what prevents you to just bind mount the usb device in your container, and specifically for Thread, apparently.

It should work, but iirc it’s an “unsupported” configuration. In other words you’re on your own getting the OTBR container working with your dongle and linked into HA’s thread integration as “preferred” network, but it should be doable.

I would love to see some documentation on how to accomplish that. AFAIK, the HA OTBR image doesn’t work outside of HAOS and the upstream OTBR image doesn’t work with HA using openthread’s supplied docker run command.

Well, there’s not much documentation because it’s unsupported. If you get it working, perhaps you can write some?

The HA team has done a lot of work getting their officially-supported container working under HAOS. I wouldn’t just expect that docker image to work outside of HAOS; that’s not what it was designed for. More likely you will have to spin up your own container using OpenThread’s image and manually configure all the skyconnect dongle settings, create a mesh network, enable the REST protocol, and import the credentials dataset. You’ll also need to make sure your IPv6 setup and mDNS are working correctly. A quick search turned up some threads where people indicate they have gotten this working, hence my suggestion that it should be doable if you are willing to do the learning and work it requires.

I’m not sure what this means? Just for fun, I just ran OTBR’s docker run command on my HA docker server and it seemed to work just fine. I don’t have a dongle so I can’t configure a network, but I can browse the OTBR web GUI. Maybe you could let us know what error you are getting? Be sure you are not missing the required quotation marks in that command.

Sorry to seem terse, but personally I think it makes zero sense to use SkyConnect with OTBR, it’s way easier, safer, and flexible to just spend $18 on a ESP32 board and flash it with OTBR, or get the ready-to-go version from GL-iNet for a bit more. Best of luck though.

Yes, how silly of me to want to use a device I purchased from Home Assistant for the feature it was advertised as having a year and a half after buying it.

There is a huge difference between getting the UI to show and getting the app to work. I appreciate the advice, but I honestly don’t know why you’re commenting on something if you don’t have any experience with it.

This is where my setup currently stands
docker-compose.yml

services:
  home-assistant:
    container_name: home-assistant
    image: ghcr.io/home-assistant/home-assistant:stable
    network_mode: host
    depends_on:
      - zwavejs2mqtt
      - zigbee2mqtt
      - frigate
    volumes:
      - $HOME/.config/home-assistant:/config
      - /var/run/docker.sock:/var/run/docker.sock
      - /run/dbus:/run/dbus:ro
    environment:
      - PUID=$PUID
      - PGID=$PGID
      - TZ=$TZ
    restart: unless-stopped
    privileged: true

  otbr:
    container_name: otbr
    image: openthread/otbr
    network_mode: host
    stdin_open: true
    tty: true
    dns: 127.0.0.1
    volumes:
      - $HOME/.config/openthread/otbr-web:/etc/default/otbr-web:ro
    privileged: true
    devices:
      - /dev/ttyUSB1
    command: >
      --radio-url spinel+hdlc+uart:///dev/ttyUSB1?uart-baudrate=460800
      --backbone-interface bond0

  matter-server:
    image: ghcr.io/home-assistant-libs/python-matter-server:stable
    container_name: matter-server
    restart: unless-stopped
    network_mode: host
    security_opt:
      - apparmor:unconfined
    volumes:
      - $HOME/.config/matter:/data/
      - /run/dbus:/run/dbus:ro
      - /etc/localtime:/etc/localtime:ro

notes:
mounting a RO file to /etc/default/otbr-web allows you to change the web UI port. You’ll notice OTBR’s docker command maps 80(container) to 8080(host), which becomes a problem if you’re also running a webserver on that same system. You can change it from 80 to something else in this file. For instance to change the web-ui port to 8080 use:

OTBR_WEB_OPTS="-I wpan0 -d7 -p 8080"

host system sysctls are set as:

$ sysctl net.ipv6.conf.all.disable_ipv6 net.ipv4.conf.all.forwarding net.ipv6.conf.all.forwarding net.ipv6.conf.all.accept_ra_rt_info_max_plen net.ipv6.conf.all.accept_ra
net.ipv6.conf.all.disable_ipv6 = 0
net.ipv4.conf.all.forwarding = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.all.accept_ra_rt_info_max_plen = 64
net.ipv6.conf.all.accept_ra = 2

:white_check_mark: Run and have access to OTBR WEB

:white_check_mark: Correctly recognize RCP dongle

:white_check_mark: Autodiscover Thread after enabling the OTBR integration http://localhost:8081

:white_check_mark: Have HA create a new preferred thread network & enable “used for Android + IOS credentials

:white_check_mark: Run python-matter-server and enable matter integration in HA ws://localhost:5580/ws

:white_check_mark: Sync Thread Credentials
Settings > Companion App > Troubleshooting > Sync Thread credentials
repeats “Updated network from Home Assistant on this device” when sync is run twice, rather than confirming the device and HA are both using the same credentials. Message now shows “Home Assistant and this device use the same network” on the second sync.

:warning: Device Pairing fails
Add device via HA Companion App Settings > Devices & services > Devices tab > Add Device button > Add Matter device. Initial pairing begins after scanning the QR code but eventually times out with “Can’t connect to thread network ha-thread-(PAN-ID)

Pairing times out after “Checking Network Connectivity” and displays “Can’t Reach Device - Make sure your phone is connected to Wi-Fi” which it is, and my wifi network is the same flat network as everything else.

I’m open to any suggestions to help me fix this issue.

Sorry, but your OP was faaaaarrr from clear regarding what you were talking/asking about.
If you had put all those information in it, be sure that at least I would have gone my way :wink:

Honestly, I don’t trust the OpenThread implementations on the ESP32 too much (just yet!). I have seen strange Thread network partitioning with ESP based Onvis S4 devices (which are not border routers but do act as OpenThread router, so not a trustworthy data point). Most ESP32 are also 2.4GHz WiFi based, they do have separate antennas, but they are close-by which is definitely not ideal. Probably fine when making sure that channels are far apart, but still, not ideal IMHO. While the LwIP stack gets better and better IPv6 support, it is certainly not as much proven as the Linux IPv6 stack.

Furthermore, the ESP border router is closed source :cry: :

The OpenThread port and ESP Border Router implementation is provided as pre-built library in ESP-IDF.

The GL-iNet stuff is also half-way closed source. So at that point, why not go for a Google/Apple one.

Personally, I’d prefer any Linux based, fully open source BR over both of these variants based ones. :man_shrugging:

What I am looking into is OpenWrt based builds. Seems like the right Linux distribution to build dedicated BRs :sunglasses:

Yeah I thought the exact same, the original post really lacked information, what you exactly tried and what your exact struggles are currently :sweat_smile:

This is a known issue. Somehow, the update doesn’t seem to work at times. It is not quite clear to me why that is, but there is a work around. See this issue report in the Android repository: Update home-assistant network Thread credentials not possible · Issue #4146 · home-assistant/android · GitHub

This is most likely related to the above: The Thread credentials are not quite right on your phone.

I have tried that and I get the same behavior. After a series of clearing G Play Store data and reboots I was able to get the confirmation message

  1. Delete Google Play Services data.
  2. Have HA create a new thread network.
  3. Set new network as preferred, set "used for Android+ IOS credentials.
  4. Settings > Troubleshooting > Sync Thread credentials repeats messages.

I’m still having pairing issues, but updated the above post with current info.

Regardless of what I tried, the device wouldn’t complete paring and timed out after “Checking Network Connectivity…” I reset Google Play Services, tried 2 separate android devices, ran the OTBR container through a macvlan network routed to the host by a separate IP, and nothing.

The device would show up in OTBR topology while the pairing was ongoing but would disappear after pairing timed out. This led me to suspect it’s an issue with matter rather than thread. The last line in the matter-server logs is

(MainThread) INFO [matter_server.server.vendor_info] Saving vendor info to storage.

Even when attempting to pair, there was nothing added in the matter logs after that.

I saw a hint to use the matter web socket instead of android device to pair, and it worked just fine with the commissioning code.

Load the local-ip:port of home assistant in a web browser, open the dev console and enter

  var socket = new WebSocket("ws://<host-ip>:5580/ws"); 

  socket.addEventListener("open", (event) => {
      console.log("WebSocket is open");
      var message = {
          "message_id": "1",
          "command": "set_thread_dataset",
          "args": {
              "dataset": "<HA THREAD Active dataset TLVs>"
          }
      };
      socket.send(JSON.stringify(message));
  });

Where <host-ip> is the local ip address of the matter-server, and <HA THREAD Active dataset TLVs> is the “Active dataset TLVs” of the thread network configured in HA. Click the (i) to get this long string

When that has completed, run the following with the device commissioning code.

  var socket = new WebSocket("ws://<host-ip>:5580/ws");
  
  socket.addEventListener("open", (event) => {
      var message = {
          "message_id": "2",
          "command": "commission_with_code",
          "args": {
              "code": "<Matter Pairing Code>"
          }
      };
      socket.send(JSON.stringify(message));
  });

Where <Matter Pairing Code> is the (in my case) 11 digit numerical code found under the pairing QR code of the matter device. Check the matter-server logs and you should see when commissioning is complete. Check HA Settings > Integrations > Matter and you’ll see the new device added.

Pretty silly to have to go through all this to pair devices. I have no idea if this will survive reboots or not, but it’s a start.

1 Like

From the slides of our Matter livestream earlier this year:

What essentially happens when going through the phone based commissioning flow is that Google does a full Matter commissioning to get the device onto the network. Then it uses the Matter multi-admin/sharing feature to commission the device with the target Matter controller (Home Assistant in your case).

The “Checking Network Connectivity…” comes from this first, phone based commissioning attempt. Unfortunately this is largely out of our control as this is all happening on your Android phone :cry: It might be that you can get logs through adb or similar, but I’ve never tried that.

It is probably some type of routing problem: E.g. is your OTBR routing correctly? Can you ping devices on the Thread network from other devices? There are a few sysctrls you need to take care of yourself to get IPv6 routing etc. going.

What I suggest you to try is to use HAOS in a test installation on a RPi, and setup with the same Thread credentials. Then see if that setup works: If yes, then it is your BR not correctly announcing/routing…

You can do the same from the frontend directly from the hidden panel at /config/matter/dashboard.

But since this relies on local Bluetooth, where we also have seen conflicts with the HA Bluetooth stack, it is (also) not reliable in all cases :cry: In the end, phone based commissioning is just more practical since you might have your new Matter device not near your Home Assistant Server. That is why we at least currently promote and focus on the phone based approach.

It seems to be working correctly. It makes a wpan0 network on the host, I see very few errors in the logs (just grabbed a tail) but it’s hard to tell with it being so chatty. I can ping any public ipv6, public temp ipv6, link-local ipv6 (fe80), but get some weird errors when trying to ping fd88. Maybe I’m doing that wrong? My bad it’s late here and the info panel 2 line stacks the ipv6 address. The fd88 ipv6 address also resolves.

Edit: I’ll also add that once the OTBR integration is set, the thread integration is auto-discovered by HA, and HA can reset/create a new thread network without any trouble.

$ ping fd88:7ccb:7e99:1:2f17:5ac7:4d23:e174
PING fd88:7ccb:7e99:1:2f17:5ac7:4d23:e174(fd88:7ccb:7e99:1:2f17:5ac7:4d23:e174) 56 data bytes
64 bytes from fd88:7ccb:7e99:1:2f17:5ac7:4d23:e174: icmp_seq=1 ttl=64 time=1737 ms
64 bytes from fd88:7ccb:7e99:1:2f17:5ac7:4d23:e174: icmp_seq=2 ttl=64 time=733 ms

I do have sysctls set on the host system, at least all that I could find since much of this is undocumented. Please let me know if I’m missing any.

The only thread device I currently have is that Aqara P2 contact sensor. I wanted to get that working before spending money on other devices.

This is absolutely huge and I wish I had known about this much earlier. It does rely on BT, which I do have available on my server but don’t use it for anything. I assume that is why the matter server volume mounts the dbus to begin with.

I’m kinda bummed neither of the android phones I have worked for commissioning and would like to figure out why. Maybe I’ll look into adb logs and see what I can find out. One of the phones is rooted, so I hope I can access what I need.

I’m also curious how this works when you don’t have any other thread border routers on the network?