Client CoAP simple
Création d’une application qui communique avec un serveur CoAP.

Le client CoAP simple montre comment créer une application client CoAP minimaliste permettant d’envoyer et de recevoir des messages CoAP.
Exécution de l'exemple
Vous pouvez exécuter l'exemple à partir de :
- Qt Creator
Ouvrez le mode « Welcome » et sélectionnez l'exemple dans « Examples ». Pour plus d'informations, consultez Qt Creator: Tutoriel : Compiler et exécuter.
- Qt Extension for Visual Studio Code
Exécutez la commande « Qt: Open Qt examples » à partir de Command Palette, puis sélectionnez l’exemple dans la liste. Pour plus d’informations, consultez Qt Extension for Visual Studio Code: Tutoriel : Compiler et exécuter.
Configuration d’un serveur CoAP
Pour utiliser l'application, vous devez spécifier un serveur CoAP. Vous disposez des options suivantes :
- Utilisez le serveur de test CoAP disponible à l'adresse
coap://coap.me. - Créer un serveur CoAP à l’aide de libcoap, FreeCoAP ou de toute autre implémentation de serveur CoAP.
- Utiliser le serveur plugtest de Californium, qui prend en charge la plupart des fonctionnalités CoAP. Vous pouvez le compiler manuellement ou utiliser une image Docker prête à l’emploi, qui compile et démarre le serveur plugtest. Les étapes d’utilisation du serveur basé sur Docker sont décrites ci-dessous.
Utilisation du serveur de test basé sur Docker
La commande suivante récupère le conteneur Docker du serveur CoAP depuis Docker Hub et le démarre :
docker run --name coap-test-server -d --rm -p 5683:5683/udp -p 5684:5684/udp tqtc/coap-californium-test-server:3.8.0Pour connaître l’adresse IP du conteneur Docker, récupérez d’abord l’ID du conteneur en exécutant la commande « docker ps », qui affichera un résultat similaire à celui-ci :
$ docker ps
CONTAINER ID IMAGE
5e46502df88f tqtc/coap-californium-test-server:3.8.0Vous pouvez ensuite obtenir l’adresse IP à l’aide de la commande suivante :
docker inspect <container_id> | grep IPAddressPar exemple :
$ docker inspect 5e46502df88f | grep IPAddress
...
"IPAddress": "172.17.0.2",
...Le serveur de test CoAP sera accessible via l'adresse IP récupérée sur les ports 5683 (non sécurisé) et 5684 (sécurisé).
Pour arrêter le conteneur Docker après utilisation, utilisez la commande suivante :
docker stop <container_id>L'<container_id> utilisé ici est le même que celui obtenu par la commande ` docker ps `.
Création d’un client
La première étape consiste à créer un client CoAP à l’aide de la classe ` QCoapClient `. Il faut ensuite connecter ses signaux afin d’être averti lorsqu’une réponse CoAP est reçue ou qu’une requête a échoué :
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
m_client = new QCoapClient(QtCoap::SecurityMode::NoSecurity, this);
connect(m_client, &QCoapClient::finished, this, &MainWindow::onFinished);
connect(m_client, &QCoapClient::error, this, &MainWindow::onError);
...Envoi de requêtes
Nous utilisons la classe ` QCoapRequest ` pour créer des requêtes CoAP. Cette classe fournit des méthodes permettant de construire des trames CoAP.
void MainWindow::on_runButton_clicked()
{
const auto msgType = ui->msgTypeCheckBox->isChecked() ? QCoapMessage::Type::Confirmable
: QCoapMessage::Type::NonConfirmable;
QUrl url;
url.setHost(tryToResolveHostName(ui->hostComboBox->currentText()));
url.setPort(ui->portSpinBox->value());
url.setPath(ui->resourceComboBox->currentText());
QCoapRequest request(url, msgType);
for (const auto &option : std::as_const(m_options))
request.addOption(option);
...Dans cet exemple, nous définissons l’URL ainsi que le type de message, puis nous ajoutons des options à la requête. Il est également possible de définir la charge utile, l’ID du message, le jeton, etc., mais nous utilisons ici les valeurs par défaut. Notez que, par défaut, l’ID du message et le jeton sont générés de manière aléatoire.
En fonction de la méthode de requête sélectionnée, nous envoyons une requête de type GET, PUT, POST ou DELETE au serveur :
...
switch (method) {
case QtCoap::Method::Get:
m_client->get(request);
break;
case QtCoap::Method::Put:
m_client->put(request, m_currentData);
break;
case QtCoap::Method::Post:
m_client->post(request, m_currentData);
break;
case QtCoap::Method::Delete:
m_client->deleteResource(request);
break;
default:
break;
}
...Pour les requêtes de type PUT et POST, nous ajoutons également m_currentData en tant que charge utile de la requête.
Pour parcourir le contenu du serveur et découvrir les ressources qui y sont disponibles, on utilise une requête de découverte:
void MainWindow::on_discoverButton_clicked()
{
...
QCoapResourceDiscoveryReply *discoverReply =
m_client->discover(url, ui->discoveryPathEdit->text());
if (discoverReply) {
connect(discoverReply, &QCoapResourceDiscoveryReply::discovered,
this, &MainWindow::onDiscovered);
...Remarque : au lieu de la classe ` QCoapReply `, nous utilisons la classe ` QCoapResourceDiscoveryReply ` pour récupérer la réponse à une requête de découverte. Celle-ci dispose du signal ` QCoapResourceDiscoveryReply::discovered `, qui renvoie la liste des `QCoapResources` qui ont été découvertes.
S’il existe des ressources observables sur le serveur (c’est-à-dire qu’elles sont de type obs), nous pouvons nous abonner aux mises à jour de cette ressource en lançant une requête d’observation:
void MainWindow::on_observeButton_clicked()
{
...
QCoapReply *observeReply = m_client->observe(url);
...
connect(observeReply, &QCoapReply::notified, this, &MainWindow::onNotified);
...Le client peut se désabonner de l'observation de la ressource en gérant le signal ` clicked() ` de l'cancelObserveButton:
...
connect(ui->cancelObserveButton, &QPushButton::clicked, this, [this, url]() {
m_client->cancelObserve(url);
ui->cancelObserveButton->setEnabled(false);
});Les réponses provenant du serveur s’affichent dans l’interface utilisateur :
void MainWindow::addMessage(const QString &message, bool isError)
{
const QString content = "--------------- %1 ---------------\n%2\n\n"_L1
.arg(QDateTime::currentDateTime().toString(), message);
ui->textEdit->setTextColor(isError ? Qt::red : Qt::black);
ui->textEdit->insertPlainText(content);
ui->textEdit->ensureCursorVisible();
}
void MainWindow::onFinished(QCoapReply *reply)
{
if (reply->errorReceived() == QtCoap::Error::Ok)
addMessage(reply->message().payload());
}
static QString errorMessage(QtCoap::Error errorCode)
{
const auto error = QMetaEnum::fromType<QtCoap::Error>().valueToKey(static_cast<int>(errorCode));
return MainWindow::tr("Request failed with error: %1\n").arg(error);
}
void MainWindow::onError(QCoapReply *reply, QtCoap::Error error)
{
const auto errorCode = reply ? reply->errorReceived() : error;
addMessage(errorMessage(errorCode), true);
}
void MainWindow::onDiscovered(QCoapResourceDiscoveryReply *reply, QList<QCoapResource> resources)
{
if (reply->errorReceived() != QtCoap::Error::Ok)
return;
QString message;
for (const auto &resource : std::as_const(resources)) {
ui->resourceComboBox->addItem(resource.path());
message += tr("Discovered resource: \"%1\" on path %2\n")
.arg(resource.title(), resource.path());
}
addMessage(message);
}
void MainWindow::onNotified(QCoapReply *reply, const QCoapMessage &message)
{
if (reply->errorReceived() == QtCoap::Error::Ok) {
addMessage(tr("Received observe notification with payload: %1")
.arg(QString::fromUtf8(message.payload())));
}
}
static QString tryToResolveHostName(const QString hostName)
{
const auto hostInfo = QHostInfo::fromName(hostName);
if (!hostInfo.addresses().empty())
return hostInfo.addresses().first().toString();
return hostName;
}Fichiers :
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.