CoAP#
The Wi-SUN CoAP component offers an application layer implementation built on top of the Wi-SUN stack and its socket API. The CoAP protocol is specifically designed as an Internet Application Protocol for constrained devices operating in lossy networks (as defined in RFC 7252). Wi-SUN FAN networks precisely fit this definition.
The CoAP implementation relies on the UDP transport layer for sending and receiving packets. Within the component, you'll find a set of helper functions that assist in building CoAP payloads, parsing CoAP packets, and freeing CoAP packets. Additionally, the CoAP Resource Handler service manages registered resources.
For resource discovery, the Resource Discovery request provides an interface to retrieve information about available resources. These resources have additional attributes beyond the URI (Uniform Resource Identifier) path, which can be selectively filtered using specific Resource Discovery requests.
Furthermore, the CoAP Notification service allows the creation and schedule of notifications for the remote host. The schedule time and send conditions can be customized based on the application requirements. To incorporate the CoAP component into the application, simply add it to the project and initialize it using sl_wisun_coap_init().
The CoAP component is compatible with third-party implementations, such as the libcoap server and client binaries.
The following block diagram shows the architecture of CoAP component: 

The following example shows the CoAP resource and notification initialization:
#include <string.h>
#include "sl_wisun_coap.h"
#include "sl_wisun_coap_rhnd.h"
#include "sl_wisun_coap_notify.h"
#define NOTIFY_URI_PATH "notify/temperature"
// CoAP Resource Handler callback
static sl_wisun_coap_packet_t *
callback_to_handle_requests(const sl_wisun_coap_packet_t * const req_packet) {
sl_wisun_coap_packet_t *resp_packet = NULL;
// Build pre-initialized CoAP packet with content response message code
resp_packet = sl_wisun_coap_build_response(req_packet, COAP_MSG_CODE_RESPONSE_CONTENT);
if (resp_packet == NULL) {
return NULL;
}
// Build your CoAP payload (resp_packet->payload_ptr)
// and set the payload length (resp_packet->payload_len)
return resp_packet;
}
static bool condition_callback(const sl_wisun_coap_notify_t * notify) {
// Build your notification condition and return the check result
(void) notify;
return true;
}
static sl_wisun_coap_packet_t *
callback_to_build_packet(const sl_wisun_coap_notify_t *notify) {
// Initialize a CoAP Packet
static sl_wisun_coap_packet_t pkt = {
.msg_code = COAP_MSG_CODE_REQUEST_PUT, // Message Code: PUT request
.msg_id = 1234, // Message ID
.msg_type = COAP_MSG_TYPE_NON_CONFIRMABLE, // Message type
.content_format = COAP_CT_TEXT_PLAIN, // Content format
.uri_path_ptr = NULL, // URI Path pointer
.uri_path_len = 0, // URI Path length
.payload_ptr = NULL, // Payload pointer
.payload_len = 0, // Payload length
.token_ptr = NULL, // Token pointer
.token_len = 0, // Token length
.options_list_ptr = NULL // Option list pointer
};
(void) notify;
// Set the URI path
pkt.uri_path_ptr = (uint8_t *)NOTIFY_URI_PATH;
pkt.uri_path_len = strlen(NOTIFY_URI_PATH);
// Set your notification payload content
// pkt.payload_ptr = your_prebuilt_buf;
// pkt.payload_len = your_payload_length;
// Return with the notification packet
return &pkt;
}
static void init_resource_and_notification(void) {
// Return value
int32_t ret = 0;
// Resource descriptor allocation
sl_wisun_coap_rhnd_resource_t coap_resource = { 0 };
// Notification handler allocation
sl_wisun_coap_notify_t notify = { 0 };
// Prepare resource with default content
sl_wisun_coap_rhnd_resource_init(&coap_resource);
// Resource URI path
coap_resource.data.uri_path = "/sensor/temperature";
// Resource type
coap_resource.data.resource_type = "temp";
// Interface
coap_resource.data.interface = "i2c-sensor";
// Function pointer to handle requests, like temperature measurement and response packet build.
// Pointer type is sl_wisun_coap_packet_t * (*)(const sl_wisun_coap_packet_t * const req_packet)
coap_resource.auto_response = callback_to_handle_requests;
// You can initialize an extended callback instead of the standard callback type.
// The extended callback receives the source address of the requests.
// The function pointer type is
// sl_wisun_coap_packet_t * (*)(const sockaddr_in6_t * const src_addr, const sl_wisun_coap_packet_t * const req_packet)
// coap_resource.auto_response_ext = extended_callback_to_handle_requests;
// Redirect response
// The callback performs a response redirection. You can build your new destination address
// and retrieve the new_addr argument
// Pointer type is
// void (*)(sockaddr_in6_t * const new_addr,const sl_wisun_coap_packet_t * const req_packet)
// coap_resource.redirect_response = NULL;
// Resource is discoverable. You can get information with resource discovery request
// GET /.well-known/core
coap_resource.discoverable = true;
// Add resource to the resource list
assert(sl_wisun_coap_rhnd_resource_add(&coap_resource) == SL_STATUS_OK);
// Set the notification ID
notify.id = "my-notification";
// Set the destination address of notification
ret = inet_pton(AF_INET6,
"2001:db8::1",
¬ify.remote_addr.sin6_addr);
assert(ret == 1);
notify.remote_addr.sin6_port = htons(5683);
// Set the schedule time of the notification, 1s is in the example
notify.schedule_time_ms = 1000;
// Initialize the condition callback.
// The callback checks the condition whether the created CoAP packet should be sent
// The function pointer type is bool (*)(const sl_wisun_coap_notify_t * notify)
notify.condition_cb = condition_callback;
// Initialize the notification handler that builds the CoAP packet
// The function pointer type is
// sl_wisun_coap_packet_t * (*)(const sl_wisun_coap_notify_t * notify)
notify.hnd_cb = callback_to_build_packet;
// Add the notification to the notification list
assert(sl_wisun_coap_notify_add(¬ify) == SL_STATUS_OK);
}