I am happy to introduce the new QtCoAP library! It is the client-side implementation of the Constrained Application Protocol (CoAP) for the Internet of Things. The library provides quick and easy way of using the CoAP protocol in your cross-platform Qt applications. Big thanks to our partners at Witekio for development and contribution of the main functionality! As it has been announced earlier, QtCoAP will be available in the new Qt 5.13 release as a part of our Qt for Automation offering, together with other IoT protocol implementations, such as MQTT, KNX and OPC UA.
What is CoAP?
CoAP was designed as a lightweight machine-to-machine (M2M) communication protocol that can run on devices with scarce memory and computing resources. It is based on the concept of RESTful APIs and is very similar to HTTP. CoAP has a client-server architecture and uses GET, POST, PUT and DELETE requests for interaction with the data. But unlike HTTP, it uses the lightweight UDP for the transport instead of TCP. Additionally, it supports some interesting features like multicast requests, resource discovery and observation.
Thanks to the low overhead and simplicity, CoAP has become one of the popular IoT protocols to be used on the embedded devices. It acts as a sort of HTTP for the embedded world.
Overview of Qt CoAP Implementation
QtCoAP supports the following functionality:
- Resource observation
- Resource discovery
- Group communication (multicast)
- Blockwise transfers
The library is really simple to use. You just need to create an instance of QCoapClient and connect its signals:
QCoapClient client; connect(&client, &QCoapClient::finished, this, &CoapHandler::onFinished); connect(&client, &QCoapClient::error, this, &CoapHandler::onError);
Now you are ready to send requests and receive replies:
// GET requests client.get(QUrl("coap://127.0.0.1:5683/resource")); // or simply client.get(QUrl("127.0.0.1/resource")); // PUT/POST requests QFile file("data.json"); // ... client.post(QUrl("127.0.0.1/resource"), file.readAll()); client.put(QUrl("127.0.0.1/resource"), file.readAll()); // DELETE requests client.deleteResource(QUrl("127.0.0.1/resource"));
Using the QCoapRequest class you can pass options and customize your requests. For example:
QCoapRequest request; request.setUrl(QUrl("127.0.0.1")); request.setPayload(file.readAll()); request.addOption(QCoapOption::UriPath, "resource"); client.put(request);
CoAP also provides a publish-subscribe mechanism achieved via “observe” requests:
QCoapReply *observeReply = client.observe(QUrl("127.0.0.1/temperature")); connect(observeReply, &QCoapReply::notified, this, &CoapHandler::onNotified);
Now your application will get notified whenever the “/temperature” resource changes.
What makes CoAP even more interesting, is the ability to find and discover CoAP resources. You can discover resources on the given host:
QCoapResourceDiscoveryReply *discoverReply = client.discover(QUrl("127.0.0.1"));
Or in the entire network:
QCoapResourceDiscoveryReply *discoverReply = client.discover();
This will send a multicast discovery request to the IPv4 CoAP multicast group. You can also run the discovery for the IPv6 nodes:
discoverReply = client.discover(QtCoap::MulticastGroup::AllCoapNodesIPv6LinkLocal); // or discoverReply = client.discover(QtCoap::MulticastGroup::AllCoapNodesIPv6SiteLocal); ... connect(discoverReply, &QCoapResourceDiscoveryReply::discovered, this, &CoapHandler::onDiscovered);
You will get several discovery replies from each CoAP device in your network. For example:
RES: 2.05 Content
RES: 2.05 Content
This will indicate, that in your network you have 2 devices running CoAP servers: one of them is connected to temperature and light sensors and the other has only a temperature sensor.
Last, but not least is security. QtCoAP library supports the following security modes:
- Authentication via pre-shared keys.
- Using X.509 certificates.
For securing the CoAP connection, you need to pass one of these modes when creating the client and configure it accordingly. For example:
QCoapClient secureClient(QtCoap::SecurityMode::PreSharedKey); QCoapSecurityConfiguration config; config.setIdentity("Client_identity"); config.setPreSharedKey("secretPSK"); secureClient.setSecurityConfiguration(config);
Please give us your feedback if you find this post interesting!