Setting Up CoAP for IoT with STM32WB Devices

Introduction

In this episode, we’ll implement direct CoAP communication between two STM32WB-based Thread nodes using OpenThread. CoAP (Constrained Application Protocol) is a lightweight, UDP-based protocol. It is ideal for resource-constrained devices. It is also a core part of Thread’s application layer.

Understanding the Role of CoAP in Thread

CoAP works similarly to HTTP but is designed for low-power networks. Devices use CoAP to expose resources (e.g., `/led`, `/temperature`) that others can query or control using standard methods like GET, POST, PUT, and DELETE.

Design Overview

We’ll implement a basic system where:

  • Device A sends a CoAP POST request to toggle an LED on Device B.
  • Device B exposes the resource /led and processes the command.

Setting Up the Server on Device B

Device B acts as a CoAP server and listens for POST requests on the /led resource:


void HandleLedRequest(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo) {
    // Toggle LED here
    BSP_LED_Toggle(LED2);

    // Optional: send an ACK
    otCoapSendEmptyAck(otInstance, aMessage, aMessageInfo);
}

void InitCoapServer() {
    otCoapResource resource = {
        .mUriPath = "led",
        .mHandler = HandleLedRequest,
        .mContext = NULL,
        .mNext = NULL
    };
    otCoapAddResource(otInstance, &resource);
}

Sending a POST Request from Device A

Device A will send a CoAP POST to Device B’s mesh-local address:


void SendToggleCommand(const otIp6Address *peerAddr) {
    otMessage *message = otCoapNewMessage(otInstance, NULL);
    otCoapMessageInit(message, OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_POST);
    otCoapMessageAppendUriPathOptions(message, "led");

    otMessageInfo msgInfo = {0};
    msgInfo.mPeerAddr = *peerAddr;
    msgInfo.mPeerPort = OT_DEFAULT_COAP_PORT;

    otCoapSendRequest(otInstance, message, &msgInfo, NULL, NULL);
}

Getting the Peer Address

You can retrieve Device B’s mesh-local address during commissioning or via multicast service discovery using the `/.well-known/core` path.

Handling the Response

Though optional, Device B can respond with an acknowledgment or a CoAP payload indicating success. This can be used by Device A to confirm the LED was toggled successfully.

Debugging and Logs

  • Ensure both devices are on the same Thread network.
  • Use RTT or UART logs to print received requests and responses.
  • Make sure the CoAP port is open and the resource path matches exactly.

Conclusion

By the end of this episode, you now have two Thread devices communicating using CoAP. This is a foundational use case in smart home and industrial IoT. In the next episode, we’ll expand this concept by adding a simple sensor readout and display over CoAP between nodes.

Leave a comment