CoAP Client and CoAP (Embedded) Server Examples
Take a look at how to set up and use Mongoose Embedded Web Server's CoAP client and server, complete with code blocks and explanations.
Join the DZone community and get the full member experience.
Join For FreeIn this blog post, I’m going to show how to implement a CoAP client and a CoAP server with the Mongoose Embedded Web Server.
To start off, download the Mongoose source code from here.
CoAP Client
Running Client Example
Take a look at what we can use in the mongoose/examples/coap_client folder on GitHub. We're going to need Makefile
in there.
Now execute coap_client
.
You’ll see an output like this:
$ ./coap_client
Using udp://coap.me:5683 as CoAP server
Sending CON...
Sent CON with msg_id = 1
ACK/RST for message with msg_id = 1 received
This example connects to a CoAP server (coap.me by default, though you can specify any server as a command line argument: ./coap_client udp://mycoapserver.com:888), sends a test message, and waits for the response and exits.
It's a pretty simple application that can be adapted to your needs.
Let’s take a look at how that works.
Client Code Explained
First of all, we need to perform the usual Mongoose tasks: initialize Mongoose manager, create an outbound connection, and choose the protocol to use. In this case, we choose CoAP:
mg_mgr_init(&mgr,0);
nc = mg_connect(&mgr, address, coap_handler);
/* Check for errors here! */
mg_set_protocol_coap(nc);
And then run the polling loop like this:
while(!s_time_to_exit) {
mg_mgr_poll(&mgr,1000);
}
Now onto the main thing: The event handler.
static void coap_handler(struct mg_connection *nc, int ev, void *p) {
switch (ev) {
case MG_EV_CONNECT: {
struct mg_coap_message cm;
uint32_t res; memset(&cm, 0, sizeof(cm));
cm.msg_id = 1;
cm.msg_type = MG_COAP_MSG_CON;
printf("Sending CON...\n");
res = mg_coap_send_message(nc, &cm);
if (res == 0) {
printf("Sent CON with msg_id = %d\n", cm.msg_id);
} else {
printf("Error: %d\n", res);
s_time_to_exit = 1;
}
break;
}
case MG_EV_COAP_ACK:
case MG_EV_COAP_RST: {
struct mg_coap_message *cm = (struct mg_coap_message *) p;
printf("ACK/RST for message with msg_id = %d received\n", cm->msg_id);
s_time_to_exit = 1;
break;
}
}
}
Here we handle three events: MG_EV_CONNECT, MG_EV_COAP_ACK and MG_EV_COAP_RST.
MG_EV_CONNECT is a general Mongoose event that occurs when the connection is established. Since Mongoose implements CoAP over UDP, it is just an event, and everything is ready to go. So here we go! We use the mg_coap_send_message function to send a test message. The first parameter is a connection to use while the second is a structure that describes the message. See the Mongoose documentation for details; actually, this structure uses the same terms as RFC 7252 does, so, you can refer to RFC 7252, as well.
MG_EV_COAP_ACK and MG_EV_COAP_RST are CoAP specific events that are invoked if ACK and RST received.
CoAP Server
Running Server Example
Ok, the next stop is the server. Go to the mongoose/examples/coap_server folder and run make.
Then run the coap_server:
$ ./coap_server
Listening for CoAP messages at udp://:5683
Now, we have a CoAP server listening on port 5683.
Run the coap_client from the previous chapter with the parameter udp://127.0.0.1:5683 (if you are running both samples on the same computer, otherwise replace 127.0.0.1 with the right IP address).
Your client output should look like this:
$ ./coap_client udp://127.0.0.1:5683
Using udp://127.0.0.1:5683 as CoAP server
Sending CON...
Sent CON with msg_id = 1
ACK/RST for message with msg_id = 1 received
Almost the same as in previous chapter, but we are using the coap.me server.
As for the coap_server output, it will be the following:
$ ./coap_server
Listening for CoAP messages at udp://:5683
CON with msg_id = 1 received
Successfully sent ACK for message with msg_id = 1
So, the server received the message, printed its ID and sent an acknowledgement (ACK, in CoAP terms).
Server Code Explained
The server code starts as any Mongoose-based server does:
mg_mgr_init(&mgr, 0);
nc = mg_bind(&mgr, s_default_address, coap_handler); mg_set_protocol_coap(nc);while (!s_sig_received) {
mg_mgr_poll(&mgr, 1000);
}
All we do is to initialize Mongoose, create a listening connection, choose a CoAP protocol and start a polling loop.
And, as in any Mongoose-based server, the details are in the event handler:
static void coap_handler(struct mg_connection *nc, int ev, void *p) {
switch (ev) {
case MG_EV_COAP_CON: {
uint32_t res;
struct mg_coap_message *cm = (struct mg_coap_message *) p;
printf("CON with msg_id = %d received\n", cm->msg_id);
res = mg_coap_send_ack(nc, cm->msg_id);
if (res == 0) {
printf("Successfully sent ACK for message with msg_id = %d\n",
cm->msg_id);
} else {
printf("Error: %d\n", res);
}
break;
}
case MG_EV_COAP_NOC:
case MG_EV_COAP_ACK:
case MG_EV_COAP_RST: {
struct mg_coap_message *cm = (struct mg_coap_message *) p;
printf("ACK/RST/NOC with msg_id = %d received\n", cm->msg_id);
break;
}
}
}
Well, it is an example, so this event handler does almost nothing. It waits for the MG_EV_COAP_CON event, and once it occurs (that means that the CON message was received), sends ACK to the sender. There is a helper to send the ACK — the mg_coap_send_ack function. It takes the connection and message ID as parameters and sends the ACK.
The rest of the events are basically ignored — this sample just prints information that they received.
Wrapping up
Although CoAP isn’t the simplest protocol to use, we do our best to make its usage as simple possible. Read CoAP RFC (7252) for protocol details and the Mongoose documentation for learning the API provided for CoAP.
Published at DZone with permission of Alexander Alashkin, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments