In Part 1 of this series, we looked at UDP vs TCP for IoT applications and the pros and cons of choosing one protocol over the other. In Part 2 we looked at communications using raw UDP packets to work out the theoretical efficiency that could be achieved. In this part, we’ll look at the CoAP protocol and contrast this with using Raw UDP communications.

CoAP is a layer that sits on top of the raw UDP protocol. In essence, CoAP is a standard set of headers that are added to each UDP packet to allow communications to be standardised. There are also a bunch of other features which the CoAP headers allow for. CoAP is a very efficient protocol, the required part of the CoAP headers adds a mere 4 bytes of overhead. There is a lot of value squeezed into those 4 bytes.

CoAP Header

CoAP Header

The first 2 bits represent the CoAP version.

The next 2 bits indicate if this message is Confirmable, Non-confirmable, an Acknowledgement, or Reset. Confirmable messages require an acknowledgment while non-confirmable messages are true fire and forget.

The next 4 bits indicate the token length and allow the token to be up to 8 bytes in length (see information on Tokens below).

The next byte is for the class code. The first 3 bits hold information about the class of response (request, success, client error, server error) and the remaining 5 bits contain more detail about the class. The codes that go into these fields are listed in the CoAP standard and can be thought of like HTTP response codes (200 = success; 404 = not found).

The final two bytes contain the message ID. Every message gets a unique message ID which is used for deduping packets should the same packet be received twice.

So in the four bytes CoAP has squeezed in:
 * Version Number
 * Message Type
 * Token Length
 * Message Class
 * A method of deduping

Tokens

If the token length in the header is greater than zero, the next bytes will contain the token. Tokens can be up to 8 bytes long. The purpose of a token is to correlate requests and responses. If for example, a device sends out 10 packets that require acknowledgement, there must be a way to identify the packet each acknowledgement belongs to.

Every response from a server to a device must echo back the token to the device. This will allow the device to keep track of which packets have been successfully acknowledged. Tokens are different from the Message ID in the header. The job of the message ID is to prevent duplication, while the tokens' job is to allow request-response messages to be matched with each other. Message IDs are often sequential and can be easily guessed, while a Token should be generated with some degree of randomness.

In practice, all COAP messages should include a token, and the longer the better.

Options

After the token comes options. Options are optional, but if used open up a range of functionality. The beauty of the options system is that they are not needed, they take up zero space. Options include things like chunked file transfers, smart proxying, and interoperability with HTTP.

CoAP Options

An option is made up of an option number (these are defined in the COAP specification) and a value. The option number is between 1 and 5 bytes long, depending on the option and the amount of information needed to be conveyed.

For example, to specify an HTTP endpoint to send the COAP message to options 3 (Uri-Host), 3 (Uri-Port), 11 (Uri-Path) and 13 (Uri-Query) can be used.

Payload

The final section of a COAP packet is the payload. This too is optional. If data can be communicated by virtue of sending an empty packet, this is perfectly acceptable. The format for the Payload area however is not defined, it can contain whatever is needed. This could be binary data or JSON, or part of an image… anything. It is up to the device and the server to agree on the data in the payload.

Message size

CoAP messages should be limited to 1280 bytes, and 1024 bytes for the payload as a general rule. For messages over this size, block-wise transfers should be used.

Block-wise transfers

Block-wise transfers are an extension to the COAP standard and permit messages larger than the maximum message size to be transmitted. Block-wise transfers are enabled with an options header 23 (Block2 — Response payload) and 27 (Block1 — Request Payload). Each block is sent as a confirmable message, meaning that each chunk can be resent if necessary.
Each block contains the size of the block, whether more blocks follow, and the block number in the sequence.

Security

ahh, yes, security. Check out part 4 of this series to see how to secure CoAP packets as this is worth a whole blog post all on its own.

Benefits of CoAP over raw UDP

Raw UDP can be made very efficient for sending data over UDP. It does have its challenges in that there are no standard libraries, and any features need to be designed and implemented. CoAP on the other hand has a range of standard libraries for many languages, adds little overhead, and introduces many of the common features that raw UDP is missing.
 One of the key things missing from CoAP however is the sending device ID is not contained in the headers. This makes it difficult to know which messages have come from which device. The best way to include a device ID with COAP is to include the information as part of the payload.

Conclusion

This article has outlined the parts of the CoAP packet structure and shown how using CoAP adds a lot of benefits over using raw UDP communications with a relatively small amount of overhead. CoAP is the best way to send IoT data over UDP.

This is part 3 of a multi-part series on UDP for IoT communications.

Check out the rest of the series
Part 1: Is UDP the right choice for IoT?
Part 2: Is it a good idea to use raw UDP packets for IoT Communications?
Part 3: CoAP — The best way to communicate over UDP for IoT applications