Implementing CoAP-Based Discovery in Thread Networks

Introduction

In a mesh network like Thread, nodes must discover services offered by other devices. They do this without relying on centralized servers. Thread supports this through CoAP-based service discovery and IPv6 multicast. In this episode, we’ll explore how multicast works. We’ll see how devices discover each other. We will also learn how to implement service discovery in OpenThread using STM32WB.

Understanding Multicast in Thread

Thread uses IPv6 multicast for efficient group messaging within the mesh. Unlike unicast (one-to-one), multicast allows one-to-many communication. This is especially useful for device discovery and broadcasting presence or status.

Common multicast addresses in Thread:

  • ff03::1 – All Thread nodes (realm-local scope)
  • ff03::2 – All Thread routers
  • ff02::1 – All nodes (link-local scope)

Service Discovery with CoAP

Thread doesn’t use traditional DNS for local discovery. Instead, it follows CoAP-based service discovery via a special resource path: /.well-known/core.

When a node sends a CoAP GET request to:

coap://[ff03::1]/.well-known/core

Every listening device responds with a list of its available CoAP resources. This way, devices know who offers what.

Example: Discovering LED Control Services

Let’s say you have multiple nodes, and some expose a `/led` CoAP endpoint. Another node sends a discovery request like this:


otMessage *message = otCoapNewMessage(instance, NULL);
otCoapMessageInit(message, OT_COAP_TYPE_NON_CONFIRMABLE, OT_COAP_CODE_GET);
otCoapMessageAppendUriPathOptions(message, ".well-known");
otCoapMessageAppendUriPathOptions(message, "core");

otMessageInfo msgInfo = {0};
msgInfo.mPeerAddr = ff03::1; // multicast to all Thread nodes
msgInfo.mPeerPort = OT_DEFAULT_COAP_PORT;

otCoapSendRequest(instance, message, &msgInfo, HandleDiscoveryResponse, NULL);

Each node that supports `/led` will respond with something like:

</led>;rt="switch";if="actuator"

Parsing and Filtering Services

To filter services based on resource type (rt) or interface (if), you can parse the response payload and match required strings. For example, look for rt="sensor" or if="monitor" to find environmental sensors.

Security Considerations

Although multicast messages are visible to all Thread nodes, only authenticated and commissioned nodes can participate. Thread ensures that only trusted devices respond or interact, protecting against unauthorized discovery.

Use Case: Smart Home Initialization

When a new controller joins a Thread mesh, it can:

  1. Multicast a discovery request
  2. Receive responses with available endpoints
  3. List and configure discovered devices (e.g., toggle lights, read sensors)

Conclusion

Service discovery and multicast make Thread truly decentralized and scalable. Devices can find each other and communicate autonomously, making the protocol ideal for dynamic environments like homes and factories. In the next episode, we will implement a real-world use case: building a two-node communication setup using CoAP on STM32WB.

Leave a comment