Simple CoAP Client▲
Simple CoAP Client demonstrates how to create a minimalistic CoAP client application to send and receive CoAP messages.
Running the Example▲
To run the example from Qt Creator, open the Welcome mode and select the example from Examples. For more information, visit Building and Running an Example.
Setting Up a CoAP Server▲
To use the application, you need to specify a CoAP server. You have the following options:
-
Use the CoAP test server located at coap://coap.me.
-
Create a CoAP server using libcoap, FreeCoAP or any other CoAP server implementation.
-
Use the Californium plugtest server, which supports most of the CoAP features. You can build it manually or use a ready Docker image, which builds and starts the plugtest server. The steps for using the docker-based server are described below.
Using the Docker-based Test Server▲
The following command pulls the docker container for the CoAP server from the Docker Hub and starts it:
docker run --
name coap-
test-
server -
d --
rm -
p 5683
:5683
/
udp -
p 5684
:5684
/
udp tqtc/
coap-
californium-
test-
server:3.8.0
To find out the IP address of the docker container, first retrieve the container ID by running docker ps, which will output something like:
$ docker ps
CONTAINER ID IMAGE
5e46502
df88f tqtc/
coap-
californium-
test-
server:3.8.0
Then you can obtain the IP address with the following command:
docker inspect &
lt;container_id&
gt; |
grep IPAddress
For example:
$ docker inspect 5e46502
df88f |
grep IPAddress
...
"IPAddress"
: "172.17.0.2"
,
...
The CoAP test server will be reachable by the retrieved IP address on ports 5683 (non-secure) and 5684 (secure).
To terminate the docker container after usage, use the following command:
docker stop &
lt;container_id&
gt;
The <container_id> here is the same as retrieved by the docker ps command.
Creating a Client▲
The first step is to create a CoAP client using the QCoapClient class. Then we need to connect its signals, to get notified when a CoAP reply is received or a request has failed:
MainWindow::
MainWindow(QWidget *
parent) :
QMainWindow(parent),
ui(new
Ui::
MainWindow)
{
m_client =
new
QCoapClient(QtCoap::SecurityMode::
NoSecurity, this
);
connect(m_client, &
amp;QCoapClient::
finished, this
, &
amp;MainWindow::
onFinished);
connect(m_client, &
amp;QCoapClient::
error, this
, &
amp;MainWindow::
onError);
...
Sending Requests▲
We use the QCoapRequest class to create CoAP requests. This class provides methods for constructing CoAP frames.
void
MainWindow::
on_runButton_clicked()
{
const
auto
msgType =
ui-&
gt;msgTypeCheckBox-&
gt;isChecked() ? QCoapMessage::Type::
Confirmable
:
QCoapMessage::Type::
NonConfirmable;
QUrl url;
url.setHost(tryToResolveHostName(ui-&
gt;hostComboBox-&
gt;currentText()));
url.setPort(ui-&
gt;portSpinBox-&
gt;value());
url.setPath(ui-&
gt;resourceComboBox-&
gt;currentText());
QCoapRequest request(url, msgType);
for
(const
auto
&
amp;option : std::
as_const(m_options))
request.addOption(option);
...
In this example, we set the URL, as well as the message type and add options to the request. It is also possible to set the payload, message ID, token, and so on, but we are using the default values here. Note that by default, the message ID and token are generated randomly.
Based on the selected request method, we send a GET, PUT, POST or DELETE request to the server:
...
switch
(method) {
case
QtCoap::Method::
Get:
m_client-&
gt;get(request);
break
;
case
QtCoap::Method::
Put:
m_client-&
gt;put(request, m_currentData);
break
;
case
QtCoap::Method::
Post:
m_client-&
gt;post(request, m_currentData);
break
;
case
QtCoap::Method::
Delete:
m_client-&
gt;deleteResource(request);
break
;
default
:
break
;
}
...
For PUT and POST requests we also add m_currentData as a payload for the request.
For browsing the contents of the server and discovering the resources available on it, a discovery request is used:
void
MainWindow::
on_discoverButton_clicked()
{
...
QCoapResourceDiscoveryReply *
discoverReply =
m_client-&
gt;discover(url, ui-&
gt;discoveryPathEdit-&
gt;text());
if
(discoverReply) {
connect(discoverReply, &
amp;QCoapResourceDiscoveryReply::
discovered,
this
, &
amp;MainWindow::
onDiscovered);
...
Instead of QCoapReply class, we use the QCoapResourceDiscoveryReply to keep the reply for a discovery request. It has the QCoapResourceDiscoveryReply::discovered signal, which returns the list of QCoapResources that has been discovered.
If there are observable resources on the server (meaning that they have the resource type obs), we can subscribe to updates on that resource by running an observe request:
void
MainWindow::
on_observeButton_clicked()
{
...
QCoapReply *
observeReply =
m_client-&
gt;observe(url);
...
connect(observeReply, &
amp;QCoapReply::
notified, this
, &
amp;MainWindow::
onNotified);
...
The client can unsubscribe from the resource observation by handling the clicked() signal of the cancelObserveButton:
...
connect(ui-&
gt;cancelObserveButton, &
amp;QPushButton::
clicked, this
, [this
, url]() {
m_client