Introduction
We set up CoAP communication in the previous episode. Now, we take it further by transmitting sensor data, like temperature or humidity. This data moves from one Thread node to another. This is a common IoT use case and demonstrates how Thread enables decentralized sensor networks.
Use Case Overview
We’ll build a setup where:
- Device A reads data from a sensor (e.g., temperature from an I2C sensor).
- Device A exposes a CoAP resource
/tempthat serves the latest sensor value. - Device B sends a GET request to
/tempand receives the reading.
Sensor Integration on Device A
Assume Device A has a sensor like the HTS221 (temperature and humidity). It periodically reads data and stores it in a variable:
// Read from sensor (simplified)
float temperature = ReadTemperatureSensor();
char tempBuffer[16];
snprintf(tempBuffer, sizeof(tempBuffer), "%.2f", temperature);
Setting Up the CoAP Resource
Create a CoAP GET handler that returns the latest sensor reading:
void HandleTempGet(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo) {
char payload[16];
snprintf(payload, sizeof(payload), "%.2f", latestTemperature);
otMessage *response = otCoapNewMessage(otInstance, NULL);
otCoapMessageInitResponse(response, aMessage, OT_COAP_TYPE_ACKNOWLEDGMENT, OT_COAP_CODE_CONTENT);
otMessageAppend(response, payload, strlen(payload));
otCoapSendResponse(otInstance, response, aMessageInfo);
}
void InitTempResource() {
otCoapResource tempResource = {
.mUriPath = "temp",
.mHandler = HandleTempGet,
.mContext = NULL,
.mNext = NULL
};
otCoapAddResource(otInstance, &tempResource);
}
Requesting Data from Device B
Device B sends a CoAP GET request to retrieve the temperature:
void RequestTempData(const otIp6Address *peerAddr) {
otMessage *message = otCoapNewMessage(otInstance, NULL);
otCoapMessageInit(message, OT_COAP_TYPE_CONFIRMABLE, OT_COAP_CODE_GET);
otCoapMessageAppendUriPathOptions(message, "temp");
otMessageInfo msgInfo = {0};
msgInfo.mPeerAddr = *peerAddr;
msgInfo.mPeerPort = OT_DEFAULT_COAP_PORT;
otCoapSendRequest(otInstance, message, &msgInfo, HandleTempResponse, NULL);
}
Processing the Response
Device B handles the response and can display it or trigger actions:
void HandleTempResponse(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo, otError aResult) {
char buffer[16];
otMessageRead(aMessage, otMessageGetOffset(aMessage), buffer, sizeof(buffer) - 1);
buffer[15] = '\0'; // ensure null termination
printf("Temperature received: %s°C", buffer);
}
Use Cases
- Environmental monitoring
- Smart agriculture (soil moisture, temperature)
- Smart homes (HVAC, room control)
Conclusion
You’ve now enabled one Thread node to act as a sensor server. Another Thread node acts as a client using CoAP GET requests. This forms the backbone of many real-world IoT applications. In the next episode, we’ll explore securing CoAP communication using DTLS and PSK.

Leave a comment