Chapter 264: Thread Protocol on ESP32-H2
Chapter Objectives
By the end of this chapter, you will be able to:
- Understand the core concepts of the IEEE 802.15.4 standard and the Thread protocol.
- Describe the different roles a device can have within a Thread network (e.g., Router, End Device).
- Explain how Thread creates a reliable, low-power, IP-based mesh network.
- Identify which ESP32 variants have the necessary hardware to support Thread.
- Configure and build a basic Thread application using the OpenThread stack in ESP-IDF.
- Use the OpenThread command-line interface (CLI) to create and manage a simple Thread network.
Introduction
While WiFi and Bluetooth are excellent for many applications, the Internet of Things has given rise to scenarios where neither is a perfect fit. Smart homes, building automation, and industrial sensor fields often require dozens or even hundreds of devices to communicate reliably over a large area, using minimal power. This is the domain of low-power wireless mesh networks.
Enter Thread, a networking protocol specifically designed for these demanding IoT environments. Unlike its predecessors, Thread is built directly on the Internet Protocol (IP), meaning every device on the network can have its own unique IPv6 address, making it a natural extension of the internet. This simplifies device-to-cloud communication and interoperability. Thread’s key promises are reliability through its self-healing mesh capabilities, robust security, and exceptionally low power consumption.
This chapter introduces the Thread protocol and its implementation on the ESP32-H2, a variant designed with a dedicated radio for the protocols that dominate this space. We will use OpenThread, Google’s open-source implementation of Thread, which is fully integrated into ESP-IDF, to build and interact with our first Thread network.
Theory
The Foundation: IEEE 802.15.4
Before we discuss Thread, we must understand its foundation. Thread does not use WiFi or Bluetooth radios. Instead, it operates on a different standard called IEEE 802.15.4. This is a standard that defines the Physical Layer (PHY) and Media Access Control (MAC) layer for low-data-rate wireless personal area networks (LR-WPANs).
- PHY Layer: Defines the radio characteristics—frequency bands (typically 2.4 GHz globally), modulation, and data rates (250 kbps in the 2.4 GHz band).
- MAC Layer: Manages how devices access the shared wireless medium to avoid collisions.
Think of 802.15.4 as the fundamental hardware and low-level transmission rules. Other protocols, like Thread and Zigbee, are built on top of it to define how networks are formed and how data is routed.
What is Thread?
Thread is a secure, IP-based wireless mesh networking protocol that runs on top of the 802.15.4 layer.
- IP-Based: This is Thread’s defining feature. Every node in a Thread network has a native IPv6 address. This avoids the need for complex, application-layer gateways to translate between proprietary protocols and the internet.
- Mesh Networking: Devices can relay messages for one another. If one device cannot communicate directly with another, its message can hop through intermediate nodes to reach its destination.
- Self-Healing: If a node in the mesh goes offline, the network automatically re-routes traffic through other available nodes to maintain connectivity.
- Secure: All communication within a Thread network is encrypted and authenticated at the network layer, ensuring that only authorized devices can join and participate.
- Low Power: Thread is designed from the ground up for battery-powered devices, with support for “sleepy” nodes that can turn their radio off for long periods to conserve energy.
mindmap root((Thread Protocol)) IP-Based ::icon(fa fa-network-wired) Every node gets an IPv6 address No complex gateways needed Seamless internet integration Mesh Networking ::icon(fa fa-project-diagram) Nodes relay messages Extends network range No single point of failure Self-Healing ::icon(fa fa-heart-pulse) Automatically re-routes traffic Adapts if a node fails Increases network reliability Secure ::icon(fa fa-lock) AES Encryption at network layer Device authentication Only authorized devices can join Low Power ::icon(fa fa-battery-half) Designed for battery operation Supports "Sleepy End Devices" (SEDs) Reduces energy consumption
Thread Network Roles
A Thread network is composed of devices with different roles and capabilities.

- Router: A mains-powered device that is always on. Routers can relay packets for other devices and help new devices join the network. A Thread network can have multiple routers.
- Leader: A single Router is dynamically elected as the Leader. Its job is to manage the set of active routers and make network-wide decisions. If the Leader fails, another Router is automatically elected to take its place.
- End Device (ED): A device that communicates only through a “parent” Router. It does not forward packets for other devices. End Devices can be battery-powered.
- Sleepy End Device (SED): A special type of End Device that can turn its radio off most of the time. It periodically wakes up to poll its parent Router for any pending messages. This is the lowest-power role.
- Border Router: A crucial component that connects a Thread network to other IP networks, like WiFi or Ethernet. It acts as a gateway, forwarding traffic between the 802.15.4 network and the outside world.
OpenThread
To make development easier, ESP-IDF integrates OpenThread, an open-source implementation of the Thread protocol released by Google. OpenThread handles all the complexities of mesh routing, security, and network management, exposing a clear API for the application developer.
Variant Notes
The ability to run Thread is determined by the presence of a specific piece of hardware: an IEEE 802.15.4 compliant radio.
- ESP32-H2: The Primary Target. This variant was designed specifically for the IoT world, featuring a dedicated 802.15.4 radio alongside a Bluetooth 5 LE radio. It is the ideal choice for pure Thread or combined Thread+BLE applications.
- ESP32-C6: Fully Supported. This powerful variant includes three radios: WiFi 6, Bluetooth 5 LE, and IEEE 802.15.4. It is perfect for creating Thread Border Routers (connecting Thread to WiFi) or other multi-protocol gateway devices.
- Original ESP32, ESP32-S2, ESP32-S3, ESP32-C3: Not Supported. These variants do not have an 802.15.4 radio. They cannot participate in a Thread network. Attempting to compile a Thread example for these targets will result in a build failure.
ESP32 Variant | IEEE 802.15.4 Radio | Thread Support | Typical Use Case |
---|---|---|---|
ESP32-H2 | ✅ | ✅ | Thread End Devices, Routers |
ESP32-C6 | ✅ | ✅ | Thread Border Routers, Multi-protocol Gateways |
ESP32, S2, S3, C3 | ❌ | ❌ | N/A (Not applicable for Thread) |
Practical Example: Creating a Thread Node with CLI
The best way to learn Thread is by interacting with it directly. We will build an application that provides a command-line interface (CLI) to the OpenThread stack. This will allow us to manually create a network, check its status, and see the node in action.
Prerequisites: An ESP32-H2 or ESP32-C6 development board.
1. Project Setup and Configuration
- Start a new project using the
openthread/cli
example from the ESP-IDF examples. - Set your target to a supported chip:
idf.py set-target esp32h2
(oresp32c6
). - Open the configuration editor:
idf.py menuconfig
.- Navigate to
Component config
->OpenThread
. Here you can pre-configure network parameters like the Network Key, PAN ID, and device role. For the CLI example, we will leave these as defaults and configure them at runtime.
- Navigate to
2. Code Walkthrough (main/main.c
)
The main
function for the CLI example is remarkably simple, as all the complexity is handled by the OpenThread component.
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_openthread.h"
#include "esp_openthread_cli.h"
#include "esp_vfs_eventfd.h"
#include "driver/uart.h"
#include "nvs_flash.h"
#include "openthread/cli.h"
#define TAG "ot_cli_main"
static void app_main(void)
{
// Initialize NVS (needed for storing network credentials)
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// Initialize the TCP/IP stack and event loop
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
// Install the OpenThread stack
esp_openthread_platform_config_t config = {
.radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(),
.host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(),
.port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(),
};
ESP_ERROR_CHECK(esp_openthread_stack_init(&config));
// Initialize the OpenThread CLI
esp_openthread_cli_init();
ESP_LOGI(TAG, "OpenThread CLI initialized.");
// The main task will now be blocked by the CLI REPL (Read-Eval-Print Loop).
// All further interaction is through the serial terminal.
}
This code simply performs the necessary initializations and then launches the CLI, which takes over the main thread.
3. Build, Flash, and Observe
- Build and flash the project:
idf.py flash monitor
. - Once the monitor starts, you will see the OpenThread banner and a
>
prompt. This is the OpenThread CLI. - Let’s create a new Thread network. Type the following commands one by one and press Enter.
- Create a new operational dataset and commit it:
> dataset init new Done > dataset commit active Done
- Bring up the network interface:
> ifconfig up Done
- Start the Thread protocol operation:
> thread start Done
- Create a new operational dataset and commit it:
- Wait a few seconds. The device will first become a
child
, and then, because it’s the only device, it will promote itself toleader
. - Check the status:
- Check the state:
> state leader Done
- Get the device’s IP addresses:
> ipaddr fdde:ad00:beef:0:0:ff:fe00:fc00 fdde:ad00:beef:0:55ca:e5a8:68d3:c1a5 fe80:0:0:0:50a3:b5a:94b1:681e Done
- Check the state:
flowchart TD A[Start: Open Terminal] --> B{Clone ESP-IDF<br>Examples Repo}; B --> C{Navigate to<br>openthread/cli example}; C --> D["Set Target<br><b>idf.py set-target esp32h2</b>"]; D --> E{"Run Menuconfig<br><i>(Optional: Review Settings)</i>"}; E --> F["Build Project<br><b>idf.py build</b>"]; F --> G{"Flash to Board<br><b>idf.py flash monitor</b>"}; G --> H(("End: Interact with<br>OpenThread CLI Prompt >")) classDef startNode fill:#EDE9FE,stroke:#5B21B6,stroke-width:2px,color:#5B21B6; classDef processNode fill:#DBEAFE,stroke:#2563EB,stroke-width:1px,color:#1E40AF; classDef decisionNode fill:#FEF3C7,stroke:#D97706,stroke-width:1px,color:#92400E; classDef endNode fill:#D1FAE5,stroke:#059669,stroke-width:2px,color:#065F46; class A startNode; class B,C,D,F,G processNode; class E decisionNode; class H endNode;
You have now successfully created a one-node Thread network! The device is acting as the Leader and is ready for other nodes to join.
Common Mistakes & Troubleshooting Tips
Mistake / Issue | Symptom(s) | Troubleshooting / Solution |
---|---|---|
Invalid Command | The CLI responds with Invalid Command after you type something. |
|
Device Won’t Join | A second device runs thread start but its state remains detached or it never becomes a child . |
|
No Leader Forms | After starting the thread, the device’s state cycles between detached and child but never becomes leader . |
|
Build Fails for Target | Compiling fails with errors about missing 802.15.4 radio support. |
|
Exercises
- Two-Node Network: Take a second ESP32-H2/C6 board. Flash it with the same
cli
example. On the first board (the leader), get the active dataset (dataset active
). On the second board, set this dataset, then bring the interface up and start the thread protocol. Use thestate
command on the second board to watch it join as achild
. Use theping
command with the IPv6 address to verify connectivity between them. - Network Scan: Before joining the network in Exercise 1, use the
scan
command on the second board. It should discover the Thread network being advertised by the first board. - Factory Reset: The OpenThread stack stores its network credentials in NVS flash. After forming a network, type
factoryreset
in the CLI. The device will reboot and will have forgotten all network information, allowing you to start fresh. This is a crucial command for debugging.
sequenceDiagram actor User participant Node1 as "Node 1 (Leader)" participant Node2 as "Node 2 (Joiner)" User->>Node1: > dataset init new User->>Node1: > dataset commit active User->>Node1: > ifconfig up User->>Node1: > thread start Note over Node1: Becomes Leader User->>Node1: > dataset active Node1-->>User: Returns dataset string User->>Node2: > dataset active [dataset_string] User->>Node2: > ifconfig up User->>Node2: > thread start Note over Node2: Joins network as Child/Router User->>Node1: > ipaddr Node1-->>User: Returns IPv6 Address of Node 1 User->>Node2: > ping [Node1_IPv6_address] Note over Node2: Verifies connectivity Node2-->>User: "1 packets transmitted, 1 packets received"
Summary
- Thread is an IP-based (IPv6) mesh networking protocol running on the IEEE 802.15.4 physical layer.
- It is designed for secure, reliable, and very low-power IoT applications.
- Key network roles include Leader, Router, and End Device. The network is self-healing if a router fails.
- The ESP32-H2 and ESP32-C6 are the only variants with the required 802.15.4 radio hardware to support Thread.
- OpenThread is the open-source stack integrated into ESP-IDF used to build Thread applications.
- The OpenThread CLI is a powerful tool for learning, debugging, and controlling a Thread network directly.
Further Reading
- ESP-IDF OpenThread Integration Guide: Espressif OpenThread Documentation
- OpenThread Official Website: openthread.io
- OpenThread CLI Reference: Official OpenThread CLI Command List