このページでは

簡易CoAPクライアント

CoAPサーバーと通信するアプリケーションの作成。

「オプションの追加」ダイアログと検出されたリソースが表示されたCoAPクライアントウィンドウ

「シンプルなCoAPクライアント」では、CoAPメッセージの送受信を行う最小限のCoAPクライアントアプリケーションの作成方法を解説します。

サンプルを実行する

サンプルは次の場所から実行できます。

CoAPサーバーの設定

アプリケーションを使用するには、CoAPサーバーを指定する必要があります。以下のオプションがあります。

  • coap://coap.me にある CoAP テストサーバーを使用します。
  • libcoap、FreeCoAP、またはその他の CoAP サーバー実装を使用して CoAP サーバーを作成します。
  • CoAPの機能の大部分をサポートしているCaliforniumplugtestサーバーを使用します。手動でビルドすることも、plugtestサーバーをビルドして起動する既製のDockerイメージを使用することもできます。Dockerベースのサーバーを使用するための手順を以下に説明します。
Docker ベースのテストサーバーの使用

次のコマンドを実行すると、Docker Hub から CoAP サーバー用の Docker コンテナを取得し、起動します:

docker run --name coap-test-server -d --rm -p 5683:5683/udp -p 5684:5684/udp tqtc/coap-californium-test-server:3.8.0

Docker コンテナの IP アドレスを確認するには、まず `docker ps` を実行してコンテナ ID を取得します。これにより、次のような出力が表示されます:

$ docker ps
CONTAINER ID        IMAGE
5e46502df88f        tqtc/coap-californium-test-server:3.8.0

その後、次のコマンドで IP アドレスを取得できます:

docker inspect <container_id> | grep IPAddress

例:

$ docker inspect 5e46502df88f | grep IPAddress
...
"IPAddress": "172.17.0.2",
...

取得したIPアドレスのポート5683(非セキュア)および5684(セキュア)で、CoAPテストサーバーにアクセスできます。

使用後に Docker コンテナを終了するには、次のコマンドを使用します:

docker stop <container_id>

ここで使用する `<container_id> ` は、`docker ps ` コマンドで取得したものと同じです。

クライアントの作成

まず、QCoapClient クラスを使用して CoAP クライアントを作成します。次に、CoAP の応答を受信したときやリクエストが失敗したときに通知を受け取れるよう、そのシグナルを接続する必要があります:

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);
    ...

リクエストの送信

CoAPリクエストの作成には、QCoapRequest クラスを使用します。このクラスは、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);
    ...

この例では、URLやメッセージタイプを設定し、リクエストにオプションを追加しています。ペイロード、メッセージID、トークンなどを設定することも可能ですが、ここではデフォルト値を使用しています。なお、デフォルトでは、メッセージIDとトークンはランダムに生成されます。

選択したリクエストメソッドに基づき、GET 、PUT 、POST 、またはDELETE のリクエストをサーバーに送信します。

    ...
    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;
    }
    ...

PUT およびPOST リクエストの場合、リクエストのペイロードとしてm_currentData も追加します。

サーバーのコンテンツを閲覧し、サーバー上で利用可能なリソースを検出するには、ディスカバリーリクエストを使用します:

void MainWindow::on_discoverButton_clicked()
{
    ...
    QCoapResourceDiscoveryReply *discoverReply =
            m_client->discover(url, ui->discoveryPathEdit->text());
    if (discoverReply) {
        connect(discoverReply, &QCoapResourceDiscoveryReply::discovered,
                this, &MainWindow::onDiscovered);
    ...

注: ディスカバリーリクエストの応答を保持するために、QCoapReply クラスの代わりに QCoapResourceDiscoveryReply を使用します。これにはQCoapResourceDiscoveryReply::discovered シグナルがあり、検出された QCoapResources のリストを返します。

サーバー上にオブザーバブルなリソース(つまり、リソースタイプが `obs` であるもの)が存在する場合、observeリクエストを実行することで、そのリソースの更新情報を購読できます:

void MainWindow::on_observeButton_clicked()
{
    ...
    QCoapReply *observeReply = m_client->observe(url);
    ...
    connect(observeReply, &QCoapReply::notified, this, &MainWindow::onNotified);
    ...

クライアントは、cancelObserveButton のclicked() シグナルを処理することで、リソースのオブザーベーションを解除できます:

    ...
    connect(ui->cancelObserveButton, &QPushButton::clicked, this, [this, url]() {
        m_client->cancelObserve(url);
        ui->cancelObserveButton->setEnabled(false);
    });

サーバーからの応答は UI に表示されます:

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;
}

ファイル:

© 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.