Skip to main content

WhirlingBits CoAP Client Documentation

The wb-idf-coap-client component provides a simplified, event-driven CoAP client for ESP-IDF projects. Built on top of , it offers an API similar to esp_mqtt_client with a config-struct + handle pattern, internal request queue, and unified event callback.

  • ✅ Simple API : Config-struct + handle pattern (like esp_mqtt_client)
  • ✅ Event-Driven : Unified callback for connect, disconnect, response, error
  • ✅ Full CRUD : GET, POST, PUT, DELETE requests
  • ✅ Observe Support : Subscribe to resource changes (RFC 7641)
  • ✅ Thread-Safe : Request functions callable from any FreeRTOS task
  • ✅ DTLS Security : Pre-Shared Key (PSK) and PKI certificate modes
  • ✅ Request Queue : Internal queue decouples callers from CoAP task
  • ✅ Token Tracking : Full token pass-through for request/response correlation
  • ✅ Location-Path : Automatic assembly from response options
  • ✅ Content Formats : Text, JSON, CBOR, XML, Link-Format, Octet-Stream
  • ✅ Configurable : Timeout, task stack, priority, queue size via Kconfig
* ┌──────────────────────────────────────┐
* │ User Application Tasks │
* │ get() / post() / put() / delete() │
* ├──────────────────────────────────────┤
* │ wb-idf-coap-client │
* │ ├── Public API (thread-safe) │
* │ ├── Internal Request Queue │
* │ ├── CoAP Processing Task │
* │ └── Event Dispatcher │
* ├──────────────────────────────────────┤
* │ libcoap (espressif/coap >= 4.3.4) │
* ├──────────────────────────────────────┤
* │ ESP-IDF (lwIP, mbedTLS, FreeRTOS) │
* └──────────────────────────────────────┘
*

The user application enqueues requests through the public API. An internal FreeRTOS task processes requests sequentially, manages the CoAP session, and dispatches events back to the user via the registered callback.

Option 1: EXTRA_COMPONENT_DIRS

# In your project CMakeLists.txt, before project()
list(APPEND EXTRA_COMPONENT_DIRS "/path/to/wb-idf-coap-client")

Option 2: idf_component.yml

dependencies:
whirlingbits/wb-idf-coap-client:
version: "*"
git: https://gitlab.whirlingbits.de/whirlingbits/wb-idf-coap-client.git

Option 3: Git Submodule

cd components
git submodule add https://gitlab.whirlingbits.de/whirlingbits/wb-idf-coap-client.git
#include "wb_coap_client.h"

static void my_handler(wb_coap_event_data_t *event, void *ctx)
{
switch (event->event) {
case WB_COAP_EVENT_CONNECTED:
ESP_LOGI(TAG, "Connected");
break;
case WB_COAP_EVENT_RESPONSE: {
wb_coap_response_t *r = event->response;
ESP_LOGI(TAG, "Response %d.%02d (%zu bytes)",
r->code >> 5, r->code & 0x1F, r->data_len);
break;
}
case WB_COAP_EVENT_DISCONNECTED:
ESP_LOGW(TAG, "Disconnected");
break;
case WB_COAP_EVENT_ERROR:
ESP_LOGE(TAG, "Error");
break;
}
}

void app_main(void)
{
wb_coap_client_config_t cfg = {
.uri = "coap://192.168.1.100",
.event_handler = my_handler,
};

wb_coap_client_handle_t client = wb_coap_client_init(&cfg);
wb_coap_client_start(client);
wb_coap_client_get(client, "/sensor/temperature");

// ... later ...
wb_coap_client_stop(client);
wb_coap_client_destroy(client);
}
ModeURI SchemeConfig Fields
NoSeccoap://security = WB_COAP_SECURITY_NONE
PSKcoaps://security = WB_COAP_SECURITY_PSK + .psk
PKIcoaps://security = WB_COAP_SECURITY_PKI + .pki

Mode

URI Scheme

Config Fields

NoSec

coap://

security = WB_COAP_SECURITY_NONE

PSK

coaps://

security = WB_COAP_SECURITY_PSK + .psk

PKI

coaps://

security = WB_COAP_SECURITY_PKI + .pki

wb_coap_client_config_t cfg = {
.uri = "coaps://server.example.com",
.security = WB_COAP_SECURITY_PSK,
.psk = {
.identity = "my-device",
.key = (const uint8_t *)"secret",
.key_len = 6,
},
.event_handler = handler,
};
extern const uint8_t ca_start[] asm("_binary_ca_pem_start");
extern const uint8_t ca_end[] asm("_binary_ca_pem_end");

wb_coap_client_config_t cfg = {
.uri = "coaps://server.example.com",
.security = WB_COAP_SECURITY_PKI,
.pki = {
.ca_cert = ca_start,
.ca_cert_len = (size_t)(ca_end - ca_start),
},
.event_handler = handler,
};

Register interest in a resource to receive automatic notifications:

wb_coap_client_observe(client, "/sensor/temperature");
// Notifications arrive as WB_COAP_EVENT_RESPONSE events
OptionDefaultDescription
WB_COAP_DEFAULT_RESPONSE_TIMEOUT_MS10000Response timeout (ms)
WB_COAP_TASK_STACK_SIZE8192Internal task stack size
WB_COAP_TASK_PRIORITY5Internal task FreeRTOS priority
WB_COAP_REQUEST_QUEUE_SIZE8Max pending requests in queue

Option

Default

Description

WB_COAP_DEFAULT_RESPONSE_TIMEOUT_MS

10000

Response timeout (ms)

WB_COAP_TASK_STACK_SIZE

8192

Internal task stack size

WB_COAP_TASK_PRIORITY

5

Internal task FreeRTOS priority

WB_COAP_REQUEST_QUEUE_SIZE

8

Max pending requests in queue

Per-instance overrides available via wb_coap_client_config_t fields: response_timeout_ms , task_stack_size , task_priority .

All responses arrive asynchronously via the event handler as WB_COAP_EVENT_RESPONSE . The wb_coap_response_t struct provides:

FieldDescription
codeCoAP response code (e.g., 0x45 = 2.05 Content)
dataResponse payload pointer (valid during callback only)
data_lenPayload length in bytes
request_pathURI path of the original request
request_methodMethod of the original request
token / token_lenCoAP token for correlation
location_pathAssembled Location-Path from response options

Field

Description

code

CoAP response code (e.g., 0x45 = 2.05 Content)

data

Response payload pointer (valid during callback only)

data_len

Payload length in bytes

request_path

URI path of the original request

request_method

Method of the original request

token / token_len

CoAP token for correlation

location_path

Assembled Location-Path from response options

CodeEnumMeaning
2.01WB_COAP_RESP_CREATEDResource created (POST)
2.02WB_COAP_RESP_DELETEDResource deleted
2.04WB_COAP_RESP_CHANGEDResource updated (PUT/POST)
2.05WB_COAP_RESP_CONTENTContent delivered (GET)
4.00WB_COAP_RESP_BAD_REQUESTMalformed request
4.01WB_COAP_RESP_UNAUTHORIZEDAuthentication required
4.04WB_COAP_RESP_NOT_FOUNDResource not found
5.00WB_COAP_RESP_INTERNAL_SERVER_ERRORServer error

Code

Enum

Meaning

2.01

WB_COAP_RESP_CREATED

Resource created (POST)

2.02

WB_COAP_RESP_DELETED

Resource deleted

2.04

WB_COAP_RESP_CHANGED

Resource updated (PUT/POST)

2.05

WB_COAP_RESP_CONTENT

Content delivered (GET)

4.00

WB_COAP_RESP_BAD_REQUEST

Malformed request

4.01

WB_COAP_RESP_UNAUTHORIZED

Authentication required

4.04

WB_COAP_RESP_NOT_FOUND

Resource not found

5.00

WB_COAP_RESP_INTERNAL_SERVER_ERROR

Server error

  • Request functions (get, post, put, delete, observe) are thread-safe and can be called from any FreeRTOS task.

  • The event handler callback is invoked from the internal CoAP task — avoid blocking operations inside it.

  • wb_coap_client_is_connected() is safe to call from any context.

  • wb_coap_client_start() / stop() / destroy() should not be called concurrently from multiple tasks.

  • Insufficient heap memory

  • NULL uri or event_handler in config

  • DNS resolution failed

  • DTLS handshake failed (check PSK/PKI credentials)

  • Server unreachable (check firewall, port 5683/5684)

  • Server not listening on the path

  • Timeout too short (increase response_timeout_ms )

  • Firewall blocking UDP

esp_log_level_set("wb_coap", ESP_LOG_DEBUG);
esp_log_level_set("coap", ESP_LOG_DEBUG);
ComponentRAM (approx.)
Client handle + internal state~512 bytes
Processing task stack8192 bytes (configurable)
Request queue (8 entries)~256 bytes
DTLS session (when using security)~10-20 KB

Component

RAM (approx.)

Client handle + internal state

~512 bytes

Processing task stack

8192 bytes (configurable)

Request queue (8 entries)

~256 bytes

DTLS session (when using security)

~10-20 KB

  • ESP-IDF Version: 5.0 or higher

  • Dependencies: espressif/coap >= 4.3.4

  • Supported SoCs: ESP32, ESP32-S2, ESP32-S3, ESP32-C3, ESP32-C6

  • Network: WiFi or Ethernet (IP connectivity required)

  • License: Apache License 2.0

  • GitLab Repository

  • Issue Tracker

  • Examples

  • wb-idf-lwm2m (LWM2M client built on this component)

Copyright (c) 2024 WhirlingBits

Licensed under the Apache License, Version 2.0. See LICENSE file in the project root for details.

Components

CoAP Client

Simplified, event-driven CoAP client wrapper for ESP-IDF.