How to: Setup an ESP32-H2 as Thread Router

Cheap Thread Router

Note: this isn’t a complete step-by-step how-to (though it covers most of the process). During the setup for the ESP-IDF in VSCode I ran into some challenges and didn’t to document those, so for now that is something to fix yourself.

Intro

After buying and installing a few Eve Motion Blind powered blinds spread over three floors, I ran into the problem of not having a Thread network that covered them all. A Homepod Mini was a start, but I did not have a place where it could reliably cover all blinds.

So I started to search for friendly priced Thread router devices. And that was a challenge: there don’t seem to be any (yet).

Extra Thread Border Routers were not preferable because of the price.

First I added a SkyConnect stick to extend the network, but that didn’t solve everything:

  • I still had single point of failures because of the location of both OTBR’s
  • One blind appeared to be in such a corner that both the Homepod and SkyConnect were not able to have a reliable connection.

By now I was pretty sure that there is no easy off-the-shelf solution and that ESP32 was the way to go.
I ordered two ESP32-H2’s and programmed them with the info from the (originally Homepod) Thread network I use in Home Assistant.

This is what I used on Windows:

  • VSCode with the following extensions:
    • ESP-IDF (Follow the installation in VSCode to get everything up and running)
    • CMake
    • CMake Tools
    • (you might need more, but the ESP-IDF wizard can take care of that, or gives you the info on what you need)

Get your Thread Network info:

  • In the HA OpenThread Border Router Add-on: enable the web port in the configuration by entering a port, saving and restarting the addon.
  • Your config should be available at: http://your.ha.ip.address:port/node/dataset/active

What to do: (might not be completely correct)

  • Connect the ESP32-H2 with USB on the UART port and check on which port on your PC it is connected (COM-port)
  • In VSCode in the ESP-IDF:
    • Create a new project
    • Select the correct target: ESP32-H2 chip (via builtin USB-JTAG)
    • Add your ESP-IDF Component directory: Leave empty
    • Choose Template
      • Select ESP-IDF
      • Search for “ot_cli”"
      • Create Project

The good stuff:

Once the project is created open the configuration by clicking on “SDK Configuration Editor (menuconfig)”.
Here you will need to search and set the following settings:

  • Enable the automatic start mode.: Enabled
  • Enable Joiner.: Enabled
    Fill the following settings with what you find on your existing HA OTBR config page:
  • OpenThread network name
  • OpenThread mesh local prefix, format /
  • OpenThread network channel
  • OpenThread network pan id (grab this one from the preferred network in the Thread Integration)
  • OpenThread extended pan id
  • OpenThread network key
  • OpenThread pre-shared commissioner key

When adjusted everything, save your config and build it.
After building, flash to your ESP32-H2 and open the monitor to check if everything works. That should be obvious, if it keeps scrolling with the same blocks of text there is probably something wrong.

Check for functionality:

  • In the monitor you can check the role of your device by typing “state” and pressing enter. This should be “router”.
  • You can also grab an IPv6 address from a Matter device in HA and try to ping it to see if the network works.
  • After waiting a bit it becomes visible as a router in the Eve Home app in the Thread Network tab.

My Experience:

  • In the Eve app some blinds are connected through my ESP-router and have an excellent connection.

My questions:

  • I get the following warning when the router is up and running, but I have not been able to find any info on it: W(3869) OPENTHREAD:[W] DuaManager----: Failed to perform next registration: NotFound

My sources:

My used sources.

ESP32H2 및 ESP 스레드 보더 라우터 보드로 스레드 네트워크 빌드  |  OpenThread
vscode-esp-idf-extension/docs/tutorial/install.md at 91590cca91b209fbfc685031007dc07fbacdfabd · espressif/vscode-esp-idf-extension · GitHub
esp-idf/examples/openthread/ot_cli at master · espressif/esp-idf · GitHub
openthread/src/cli/README.md at 000f5fcb30d7e2853a4d1bb0f7d21cf0e52c00aa · openthread/openthread · GitHub

2 Likes

That is not Espressif Thread border router development board, but just a ESP32-H2 ?

I have this one: ESP32-H2-DevKitM-1 - - — esp-dev-kits latest documentation

I believe its the cheapest one with Thread-support I could find.

Also see ESP32H2 및 ESP 스레드 보더 라우터 보드로 스레드 네트워크 빌드  |  OpenThread.
I skipped the ESP Thread Border Router Board.

1 Like

Basic the part that I skipped when I built my OTBR’s. So I could have used an ESP32-H2 as supporting router instead of a second OTBR. Good to know.

Is there a way to do this with an existing non-openThread network (Google Nest, Echo, Homepod, etc.)? Don’t think there is an easy way to get the network key from them and put it on the ESP32s

My Thread network started out with a Homepod Mini.
I setup that network als main network in HA and shared the credentials. This way the HA Thread network had the same key as the original network.

For someone who doesn’t own a SkyConnect stick or similar, the easiest way to achieve this is to use ESP Matter. The setup/steps will be different from the OP but it’s still relatively straightforward with this guide:
https://docs.espressif.com/projects/esp-matter/en/latest/esp32/developing.html#esp-matter-setup

Once you flash one of the examples (I used the light one) to your esp32 (h2, c5, or c6) with the thread config, it will startup as a router and all you need to do is add them to your existing thread network using matter. This is by far the cheapest way to extend one’s thread network range.

Update: You can use ESP Launchpad to flash without using command line and/or the esp-idf tool. ESP Launchpad

2 Likes

For anyone else who couldn’t get their config from the URL above. This post helped me get my Thread network details including pre-shared key. Finding the Network Key for Thread Network

Thank you, I now have 3 new thread routers running and can see them on my HA OTBR web page, my only stumbling block was not realizing that “OpenThread pre-shared commissioner key” is PSKc and “OpenThread network pan id” is in hex, for example 444 is entered as: 0x01bc

Thanks for sharing this! As I was trying to implement the steps in your post, I actually found an even easier way to create a router device - if you have ESP Home that is. They just recently added Thread support to ESP Home.

The only piece of data you need to retrieve from your existing Thread network is the TLV string, which can be found directly through HA. Go to Settings → Devices & Services → Integrations → Thread. Click the Cogwheel by the existing Thread integration, then click the ⓘ by your Thread network; the TLV string is the last entry under Active Dataset TLVs.

Here is a working config file (I have some extra stuff in mine since I am using a non-Espressif ESP32-C6 device which seems to require that).

esphome:
  name: thread-router
  friendly_name: Thread Router

esp32:
  board: esp32-c6-devkitm-1
  flash_size: 4MB
  variant: esp32c6
  framework:
    type: esp-idf
    #Can be dev, latest, recommended, or check https://github.com/espressif/esp-idf/releases
    version: "5.2.1"
    #check platform_version @ https://github.com/platformio/platform-espressif32/releases/
    platform_version: 6.7.0
    sdkconfig_options:
      CONFIG_OPENTHREAD_ENABLED: y
      CONFIG_ENABLE_WIFI_STATION: y
      CONFIG_USE_MINIMAL_MDNS: y
      CONFIG_ESPTOOLPY_FLASHSIZE_4MB: y


logger:

# Enable Home Assistant API
api:
  encryption:
    key: <device encryption key>

network:
  enable_ipv6: true

openthread:
  tlv: <your tlv string from home assistant>

I think this config should work for regular C6 or H2 devices (not tested):

esphome:
  name: thread-router
  friendly_name: Thread Router

esp32:
  board: esp32-c6-devkitm-1
  framework:
    type: esp-idf

logger:

# Enable Home Assistant API
api:
  encryption:
    key: <device encryption key>

network:
  enable_ipv6: true

openthread:
  tlv: <your tlv string from home assistant>

You can go to the web port of the Open Thread Border Router add on as described in the OP and then go to Topology to see if it worked. You should see something like this to confirm that your new device is acting as a router. It may take a while for it to show, and an even longer while for any children to actually connect to it.

This should also support any sensors etc that you can normally use in ESPHome, although I haven’t tested that yet. I will keep an eye on the stability of this device and then probably convert my other ESPHome devices to use Thread instead of WIFI as well.

7 Likes

Hi - I would like to start with Thread / Matter. I have ESP-H2 already and want to use it as border router. I have as well a bunch of XIAO SEEED C6 that will control LED strips via mosfets - would like to be able to turn them on anf off via fade in/off effect.

I have done one via WiFi but would like to have them via Thread/Matter.

esphome:
  name: nightlight-n1
  friendly_name: NightLight_N1
  platformio_options:
    platform: https://github.com/lucaskatayama/platform-espressif32.git#feat/seeed_xiao_esp32c6.json

esp32:
  board: seeed_xiao_esp32c6
  variant: ESP32C6
  framework:
    type: esp-idf
    version: 5.3.0
    platform_version: 6.9.0
    sdkconfig_options:
      CONFIG_ESPTOOLPY_FLASHSIZE_4MB: y

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "my_secret_key_here"

ota:
  - platform: esphome
    password: "my_pwd_here"

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Nightlight-N Fallback Hotspot"
    password: "some_pwd_here"

captive_portal:

output:
-  platform: ledc
   pin: GPIO18
   frequency: 20000Hz 
   id: ledcout 
-  platform: ledc
   pin: GPIO20
   frequency: 20000Hz 
   id: ledcout2 

light:
  - platform: monochromatic
    output: ledcout
    name: SkirtLight_N1_1
    default_transition_length: 3s
    restore_mode: RESTORE_DEFAULT_OFF
  - platform: monochromatic
    output: ledcout2
    name: SkirtLight_N1_2
    default_transition_length: 3s
    restore_mode: RESTORE_DEFAULT_OFF

How to do this via Matter/Thread ?

To be clear, this topic is about setting up a esp32-h2 as a Thread routing node (repeater), not a Thread Border Router. A routing node is Thread-only and extends your mesh; a TBR is Thread and WiFi (or Ethernet) and forwards IP packets back and forth between them.

You can flash a esp32-h2 with “radio coprocessor” (RCP) firmware from Espressif in order to use it as the Thread half of a TBR. I use an OTBR docker container on my HA server coupled with RCP-flashed esp32-h2 to make a border router, but there are other ways too. So you cannot make a Thread Border Router with esphome.

You can flash a esp32-h2 with esphome firmware if you want to customize a device and communicate over a Thread network. Esphome does not speak Matter, it has its own API (or MQTT) for control. So you cannot make a Matter-over-Thread device with esphome.

The only way to make custom Matter-over-Thread devices, as of today, is to use Espressif’s Zero Code framework. However be advised that HA matter server does not recognize the Zero Code attestation certificates, so these devices only work on third-party Matter controllers (Apple/Google Home, for example). EDIT: see post 16 below for hidden option to enable Zero Code certificates in HA.

1 Like

Ah - ok - so is there any way to modify end device to turn on/off with fading effect instead of sharp switch state?

We do include the Matter test attestation certificate in the Matter Python Server. We can also add additional (test) attestation certificate if that is helpful. Do you happen to have a link to the Zero Code attestation certificate? Or does this get generated for each user?

I’ve seen several reports of Zero Code commission failures, in addition to my own experience, including one that python-matter-server 6.1.2 was the last version to work. Unfortunately I don’t know how to extract/examine the certificate but I’m happy to try if it’ll help.

Incidentally I only flashed a zero code H2 because I wanted a routing node for my Thread mesh (to bring this back on-topic). It does add to the mesh, it just never joins the fabric, so works fine as a router, and as a test IPv6 / zeroconf node.

Hm, I see, this was before some rework of how we fetch the certificates. Maybe the Zero Code certificates are only available from test net DCL, which we disabled with PR 786.

You can (re)enable test net DCL by adding --enable-test-net-dcl to the “Extra Matter Server arguments” configuration, then restart the add-on. Can you try if that makes commissioning Zero Code device work again?

Edit: Actually, there is separate “Enable test-net DCL usage.” option (enable “Show unused optional configuration options” to see it). That options sets that flag. So no need to use the Extra Matter Server arguments :smile: .

Hehe ok, interesting, yeah I guess the commissioning comes far enough then to add the device to the Thread network. :+1:

It does! I use the container install and added the option to my docker-compose file. Was just able to use the sharing code from Apple Home to commission to HA. Thank you for pointing this out! I’m mainly happy to verify it definitely wasn’t a Thread routing problem. :blush:

Ok - have already enabled thread border router and now I think I am interested in the topic here.

My main question is that I have now some H2 to HAOS via OTBR plugin - have also populated one C6 node with controller of 2 light nodes (2 light strips with fade effect via MOSFET). Plan is to add some temp/humid/light sensors and expose them in HA.

ATM my network has only one BR and one child - I have noticed quite poor range of this solution what is understandable as this should be a mesh network. My question is:
can I combine node and router in one device ? I mean - I know my network will grow and will cover whole house, but I like Zigbee philosophy where every power (not battery) enabled node acts as a router/repeater - what build quite good network resiliance. What can I do to achieve it in Thread?

Yes, that is how it will work if you use the ESP Home setup I shared above.
I added sensors like you normally would and that device is now both a router in the Thread mesh network, and also a normal node in ESPHome that exposes its sensors to Home Assistant. In my case, it’s an ultrasonic distance sensor that is reading a tank level.

is there any special set that need to be done to allows it to be a router or it switch itself to router mode if something ask it to connect?