Introducing QtCoAP

Published Thursday June 6th, 2019
10 Comments on Introducing QtCoAP
Posted in Automotive, Embedded, Internet of Things | Tags: , , , ,

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 MQTTKNX 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
  • Security

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:

Host 1:

RES: 2.05 Content
;rt="temperature-c";if="sensor";obs,
;rt="firmware";sz=262144

Host 2:

RES: 2.05 Content
;rt="temperature-c";if="sensor";obs,

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.

Security

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!

Do you like this? Share it
Share on LinkedInGoogle+Share on FacebookTweet about this on Twitter

Posted in Automotive, Embedded, Internet of Things | Tags: , , , ,

10 comments

Marc Van Daele says:

Looks promising!

Some questions:
– is it possible to control whether messages are sent confirmable or not-confirmable?
– when sending a confirmable message do you get a signal when it can’t be delivered (eg the server went down)?
– when observing a resource, do you get a signal when the server disappeared?

Sona Kurazyan says:

Thanks for the comment!

– Yes, it is possible. As it is mentioned above, you can use the QCoapRequest class, if you want to customize your request, for example, by specifying whether it’s confirmable or not. You can check this example for details.
– You will always get signals on success and failure of the request, no matter it is confirmable or not.
– For observe requests when the server disappears, I guess, it depends on the server. If it sends a notification with the proper response code before shutting down, then the client will be notified. If the server simply disappears (for example because of a crash), the client will simply stop receiving notifications.

I hope this answers your questions.

Marc Van Daele says:

I installed, using the MaintenaceTool, preview Qt 5.13.0.-rc (201906040540) and tried building the example you mentioned (thanks for that!). However, I run into “Unknown module(s) in QT: coap”. Is it possible that QtCoap is not included yet in this prerelease?
I’m on Ubuntu 16.04

Sona Kurazyan says:

Have you also installed Qt for Automation Qt 5.13.0.-rc (you have to have a commercial license for it)? Alternatively, you can build the module yourself, the sources are available here https://code.qt.io/cgit/qt/qtcoap.git under GPL3 license.

Marc Van Daele says:

I’ve been able to compile the quicksecureclient, but I don’t succeed yet in connecting to my server.
However, `coap-client -u 9910f17aee0f40aca55b3bb74e0a66a9 -k JUId20phdhfcECPK coaps://192.168.1.3:5684/15001` (from libcoap.net) works just fine.
A wireshark capture indicates that it already fails in the DTLS “Client Hello” where you are using DTLS v1.2 and coap-client seems to use DTLS v1.0. Not sure what the differences are and if/where I can change/configure this?
I guess this is not the best place to have technical discussions. Can you suggest a better place?

Marc Van Daele says:

I built QtCoap from source and was able to compile and start the examples.
However I can’t connect to my (existing) Coap server.
As far as i can tell this is because Qt5 uses “OpenSSL 1.0.2k-fips 26 Jan 2017” (as returned by `QSslSocket::sslLibraryBuildVersionString()`)
However, Coap (or my coap server) expects Cipher `TLS_PSK_WITH_AES_128_CCM_8` which is only available from OpenSSL 1.1.

I’m probably overlooking something but I can’t seem to find how to use Qt5 with OpenSSL1.1?

Sona Kurazyan says:

That’s true, the ciphers required for CoAP are available from OpenSSL 1.1, so thanks for reporting the issue, we are working on switching to 1.1 version already. If you need this urgently, you can build Qt from sources and use the desired OpenSSL version (more info can be found here).

Silas Parker says:

What licence will this be released under?
Is it Commercial + GPL3 like the MQTT library?

Sona Kurazyan says:

Yes, that’s right.

liame4947 says:

thank you!!!

Leave a Reply

Your email address will not be published.

Get started today with Qt Download now