My experience with Thread and Nanoleaf bulb

With some difficulty, I managed to get a test system up running on 4 docker containers combining HA, matter-server, OTBR, and Avahi daemon. The goal is to do it all open-source- I’m trying to avoid Nest hubs/ Alexa/ Homekint. I had to do some tricks, like a script to force the thread data to populate on the matter server. I also did

But, despite all my efforts, the app’s commissioning stage kept saying I didn’t have an OTBR configured. Rough steps -

  • Flash ConbeeIII with Thread firmware

  • Docker container with HA

  • Container with OTBR using a mac-vlan network in docker-compose, or with bridge network and mirrored by Avahi (both tried).

  • Container with python-matter-server on macvlan

  • Container running Avahi for mirroring the udp and mDNS to the main network, for the OTBR Docker container running “bridge” for network. This did work to idnetify the Thread network on apps like Nanoleaf, but got further functionality by having an individually-addressable IP on my primary network. I noticed a difference with the Google Home sample/dev test app- I was able to easily receive the dataset (not possible with Avahi)

  • Nanoleaf app to identify OTBR (but couldn’t get it to associate fully in Android) and the Nanoleaf A19 bulb. This is where other people have had success, but I didn’t. Others did manage to associate OTBR with the Nanoleaf network, but I couldn’t.

The final dead-end was that the HA companion app on Android seems to use the boilerplate Google Home code for pairing. I got all the way to the final screen, but received an error - “Your device requires a Thread border router, connect your border router, then try setting up your device”. A bit of a kick in the face, but this probably means you would need the official Google products (nest hub, etc) for commissioning, because this is all that’s allowed as Thread routers in Google Home app. OTBR instances are not an option.

Finally I tried a python script on the matter-server container to force the pairing to the bulb’s QR code’s “MT” number, but the response was that it failed.

I’m no expert- if I knew more specific things to look for in docker-compose logs besides “error”, or potentially other ways to view the matter-server’s traffic and activity, it would help. Or, if there are tricks via Nanoleaf to (for example) manually add the thread network’s dataset (obtained via ot-ctl dataset active -x) to the app’s files using adb or something, that could be viable to “force” Nanoleaf app to join the open-source router.

Finally, if there’s been a hack to make the HA SkyConnect dongle a “valid” OTBR in the final pairing step of “Add Matter Device” in HA’s Android companion app, I would certainly buy it.

Used Grok Ai for assistance thru this project - it seems to have the best “memory” and is therefore great for long complicated processes like this

Here’s my docker-compose code

version: '3'
services:
  homeassistant:
    image: homeassistant/home-assistant:stable
    container_name: homeassistant
    restart: unless-stopped
    environment:
      - TZ=Your/Timezone
    volumes:
      - /srv/homeassistant/config:/config
    networks:
      home_network:
        ipv4_address: 192.168.0.101
    ports:
      - "8123:8123"

  otbr:
    image: openthread/otbr:latest
    container_name: otbr
    privileged: true
    restart: unless-stopped
    networks:
      home_network:
        ipv4_address: 192.168.0.102
    devices:
      - "/dev/ttyUSB0:/dev/ttyUSB0:rwm"
    cap_add:
      - SYS_RAWIO
      - NET_ADMIN
      - NET_RAW
    environment:
      - RADIO_URL=spinel+hdlc+uart:///dev/ttyUSB0?uart-baudrate=115200
      - TUN_INTERFACE_NAME=wpan0
    volumes:
      - /srv/homeassistant/otbr/config:/config
      - /srv/homeassistant/otbr/thread_data:/var/lib/thread
    sysctls:
      - 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
    command: bash -c "source /config/thread_init.sh"

  avahi:
    image: flungo/avahi
    container_name: avahi
    network_mode: "host"
    volumes:
      - /var/run/dbus:/var/run/dbus
      - /var/run/avahi-daemon/:/var/run/avahi-daemon/
      - /srv/homeassistant/matter/data/matter.service:/etc/avahi/services/matter.service  
    cap_add:
      - NET_ADMIN
      - NET_RAW
    environment:
      - REFLECTOR_ENABLE_REFLECTOR=yes
        
  matter-server:
    image: ghcr.io/home-assistant-libs/python-matter-server:stable
    container_name: matter-server
    restart: unless-stopped
    security_opt:
      - apparmor:unconfined
    volumes:
      - /srv/homeassistant/matter/data:/data
#     - /run/dbus:/run/dbus:ro
    networks:
      home_network:
        ipv4_address: 192.168.0.103
    entrypoint: /bin/sh -c "pip install websocket-client && python -c \"import websocket; print('websocket-client installed')\" && matter-server --storage-path /data --paa-root-cert-dir /data/credentials --bluetooth-adapter 0"
#   command: bash -c "python3 -m pip install websocket-client && python3 /data/dataset_push.py"

networks:
  home_network:
    driver: macvlan
    driver_opts:
      parent: enP3p49s0 # or the interface your network is on
    ipam:
      config:
        - subnet: "192.168.0.0/24"
          gateway: "192.168.0.1"
  bridge_network:
    driver: bridge

The companion app uses the Android framework for commissioning indeed, which reads the internal Thread Network data store. However, that said, it is possible to add our own Thread network to the datastore. Make sure to sync the Thread credentials. Essentially follow the steps outlined here: Thread - Home Assistant (specifically the Settings > Companion app > Troubleshooting, then select Sync Thread credentials step).

For that to work you’d need at the very least the set_thread_dataset websocket command. There is also the built-in web interface on the Python Matter Server which allows to do “local” commissioning. See also Matter Pairing/Commissioning hints.

1 Like

Bingo!! Wow I had missed that ONE detail, but once the credentials were pulled from the companioin app’s “Troubleshooting” section, I still wasn’t able to sync the bulb via the Matter in the integration. It bugged out on “connecting to wifi”… which is odd because it was connected to the HA instance over WiFi. I believe it was a permissions issue.

However, I tried in the Nanoleaf app, and the credentials had now populated fully, and it joined easily! Now, on OTBR’s web interface, I can see the device in “topology” confirming it’s part of OTBR

I still haven’t been able to get the HA instance to pick up the new addition to the Thread network as a device or entity, but I definitely see the light at the end of the tunnel now!

Hm, but where to did you add the device then? Google Home? When commissioning a new device via the Compagnion App (e.g. by adding the Matter device from within the App) then it should be added directly to Home Assistant.

1 Like

I commissioned via Nanoleaf Android app. It was part of a test setup since I’ve corrupted a few SD cards and want to migrate away from HA-Os on Pi4 to a more robust SBC or Mac

But, I had some trouble commissioning via HA Android. Perhaps app permissions, or something not quite right w matter-server container? It was giving me a WiFi error while being connected to HA over WiFi lol

Either way, commissioning a device at all gives me confidence to buy thread devices (Black Friday!) and proceed getting the new HA machine functional. Like it seems like you could dump the device config from ot-ctl and stick it in the Thread config json in HA or something.

Thanks for following the process and solving the crux almost instantly! I was 5 minutes from taking down the test setup with no success, but your were too fast :grin: