diff options
author | Sona Kurazyan <sona.kurazyan@qt.io> | 2019-03-05 17:30:04 +0100 |
---|---|---|
committer | Sona Kurazyan <sona.kurazyan@qt.io> | 2019-04-17 08:05:16 +0000 |
commit | f633087e26592c0b5e4a10d3895e03c267823a4f (patch) | |
tree | a1380f18180b7d54f6995d616560f3fbd3a83a12 | |
parent | a9a0561e52fd6fb4352d3fc178ee549df9add576 (diff) |
Add QML-based multicast discovery example
Change-Id: If210c040ec40a828d4c997251ef2a635e2e70d32
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
-rw-r--r-- | examples/coap/coap.pro | 1 | ||||
-rw-r--r-- | examples/coap/quickmulticastclient/main.cpp | 80 | ||||
-rw-r--r-- | examples/coap/quickmulticastclient/main.qml | 222 | ||||
-rw-r--r-- | examples/coap/quickmulticastclient/qml.qrc | 5 | ||||
-rw-r--r-- | examples/coap/quickmulticastclient/qmlcoapmulticastclient.cpp | 103 | ||||
-rw-r--r-- | examples/coap/quickmulticastclient/qmlcoapmulticastclient.h | 91 | ||||
-rw-r--r-- | examples/coap/quickmulticastclient/quickmulticastclient.pro | 24 |
7 files changed, 526 insertions, 0 deletions
diff --git a/examples/coap/coap.pro b/examples/coap/coap.pro index 0a8f1c3..dcac089 100644 --- a/examples/coap/coap.pro +++ b/examples/coap/coap.pro @@ -1,5 +1,6 @@ TEMPLATE = subdirs SUBDIRS += \ + quickmulticastclient \ simplecoapclient \ consolecoapclient diff --git a/examples/coap/quickmulticastclient/main.cpp b/examples/coap/quickmulticastclient/main.cpp new file mode 100644 index 0000000..dec9b81 --- /dev/null +++ b/examples/coap/quickmulticastclient/main.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the QtCoap module. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlcoapmulticastclient.h" + +#include <QGuiApplication> +#include <QQmlApplicationEngine> + +int main(int argc, char *argv[]) +{ + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + + qmlRegisterType<QmlCoapMulticastClient>("CoapMulticastClient", 1, 0, "CoapMulticastClient"); + + // Register the QtCoap namespace + qmlRegisterUncreatableMetaObject(QtCoap::staticMetaObject, "qtcoap.example.namespace", 1, 0, + "QtCoap", "Access to enums is read-only"); + + const QUrl url(QStringLiteral("qrc:/main.qml")); + QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, + &app, [url](QObject *obj, const QUrl &objUrl) { + // Exit with error, if the object for main.qml could not be loaded. + if (!obj && url == objUrl) + QCoreApplication::exit(-1); + }, Qt::QueuedConnection); + engine.load(url); + + return app.exec(); +} diff --git a/examples/coap/quickmulticastclient/main.qml b/examples/coap/quickmulticastclient/main.qml new file mode 100644 index 0000000..da28624 --- /dev/null +++ b/examples/coap/quickmulticastclient/main.qml @@ -0,0 +1,222 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the QtCoap module. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.12 +import QtQuick.Window 2.12 +import QtQuick.Controls 2.12 +import QtQuick.Layouts 1.13 +import CoapMulticastClient 1.0 +import qtcoap.example.namespace 1.0 + +Window { + visible: true + width: 480 + height: 480 + title: qsTr("Qt Quick CoAP Multicast Discovery") + + function addResource(resource) { + resourceModel.insert(0, {"host" : resource.host, + "path" : resource.path, + "title" : resource.title}) + } + + CoapMulticastClient { + id: client + onDiscovered: addResource(resource) + + onFinished: { + statusLabel.text = (error === QtCoap.NoError) + ? qsTr("Finished resource discovery.") + : qsTr("Resource discovery failed with error code: %1").arg(error) + } + + onError: + statusLabel.text = qsTr("Resource discovery failed with error code: %1").arg(error) + } + + GridLayout { + anchors.fill: parent + anchors.margins: 10 + columns: 2 + + Label { + text: qsTr("Host:") + } + + RowLayout { + spacing: 5 + + ComboBox { + id: groupComboBox + textRole: "group" + Layout.preferredWidth: 210 + model: ListModel { + id: cbItems + ListElement { + group: qsTr("IPv4 CoAP Nodes") + address: "224.0.1.187" + value: QtCoap.AllCoapNodesIPv4 + } + ListElement { + group: qsTr("IPv6 Link Local CoAP Nodes") + address: "ff02::fd" + value: QtCoap.AllCoapNodesIPv6LinkLocal + } + ListElement { + group: qsTr("IPv6 Site Local CoAP Nodes") + address: "ff05::fd" + value: QtCoap.AllCoapNodesIPv6SiteLocal + } + ListElement { + group: qsTr("Other") + address: "" + value: -1 + } + } + + delegate: ItemDelegate { + width: groupComboBox.width + contentItem: Column { + Text { text: group } + Text { text: address } + } + highlighted: groupComboBox.highlightedIndex === index + } + } + + TextField { + id: customGroupField + placeholderText: qsTr("<Custom Group>") + enabled: groupComboBox.model.get(groupComboBox.currentIndex).value === -1 + Layout.fillWidth: true + } + } + + Label { + text: qsTr("Port:") + } + + TextField { + id: portField + text: "5683" + placeholderText: qsTr("<Port>") + inputMethodHints: Qt.ImhDigitsOnly + Layout.preferredWidth: 80 + } + + Label { + text: qsTr("Discovery Path:") + } + + TextField { + id: discoveryPathField + text: "/.well-known/core" + placeholderText: qsTr("<Resource Discovery Path>") + inputMethodHints: Qt.ImhUrlCharactersOnly + Layout.fillWidth: true + } + + Button { + id: discoverButton + text: qsTr("Discover") + Layout.columnSpan: 2 + + onClicked: { + var currentGroup = groupComboBox.model.get(groupComboBox.currentIndex).value; + + var path = ""; + if (currentGroup !== - 1) { + client.discover(currentGroup, parseInt(portField.text), + discoveryPathField.text); + path = groupComboBox.currentText; + } else { + client.discover(customGroupField.text, parseInt(portField.text), + discoveryPathField.text); + path = customGroupField.text + discoveryPathField.text; + } + statusLabel.text = qsTr("Discovering resources at %1...").arg(path); + } + } + + ListModel { + id: resourceModel + } + + ListView { + id: resourceView + model: resourceModel + clip: true + Layout.columnSpan: 2 + Layout.fillHeight: true + Layout.fillWidth: true + + delegate: Rectangle { + width: resourceView.width + height: 60 + color: "lightgray" + border.color: "darkgray" + radius: 5 + + Column { + topPadding: 5 + leftPadding: 5 + Text { text: qsTr('<b>Host:</b> %1').arg(host) } + Text { text: qsTr('<b>Resource:</b> %1').arg(path) } + Text { text: qsTr('<b>Title:</b> %1').arg(title) } + } + } + } + Label { + id: statusLabel + Layout.columnSpan: 2 + Layout.fillWidth: true + } + } +} diff --git a/examples/coap/quickmulticastclient/qml.qrc b/examples/coap/quickmulticastclient/qml.qrc new file mode 100644 index 0000000..5f6483a --- /dev/null +++ b/examples/coap/quickmulticastclient/qml.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>main.qml</file> + </qresource> +</RCC> diff --git a/examples/coap/quickmulticastclient/qmlcoapmulticastclient.cpp b/examples/coap/quickmulticastclient/qmlcoapmulticastclient.cpp new file mode 100644 index 0000000..6d0a1fd --- /dev/null +++ b/examples/coap/quickmulticastclient/qmlcoapmulticastclient.cpp @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the QtCoap module. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmlcoapmulticastclient.h" + +#include <QCoapDiscoveryReply> +#include <QLoggingCategory> + +Q_LOGGING_CATEGORY(lcCoapClient, "qt.coap.client") + +QmlCoapMulticastClient::QmlCoapMulticastClient(QObject *parent) + : QCoapClient(QtCoap::NoSec, parent) +{ + connect(this, &QCoapClient::finished, this, + [this](QCoapReply *reply) { + if (reply) + emit finished(reply->errorReceived()); + else + qCWarning(lcCoapClient, "Something went wrong, received a null reply"); + }); +} + +void QmlCoapMulticastClient::discover(const QString &host, int port, const QString &discoveryPath) +{ + QUrl url; + url.setHost(host); + url.setPort(port); + + QCoapDiscoveryReply *discoverReply = QCoapClient::discover(url, discoveryPath); + if (discoverReply) { + connect(discoverReply, &QCoapDiscoveryReply::discovered, + this, &QmlCoapMulticastClient::onDiscovered); + } else { + qCWarning(lcCoapClient, "Discovery request failed."); + } +} + +void QmlCoapMulticastClient::discover(QtCoap::MulticastGroup group, int port, + const QString &discoveryPath) +{ + QCoapDiscoveryReply *discoverReply = QCoapClient::discover(group, port, discoveryPath); + if (discoverReply) { + connect(discoverReply, &QCoapDiscoveryReply::discovered, + this, &QmlCoapMulticastClient::onDiscovered); + } else { + qCWarning(lcCoapClient, "Discovery request failed."); + } +} + +void QmlCoapMulticastClient::onDiscovered(QCoapDiscoveryReply *reply, + const QVector<QCoapResource> &resources) +{ + Q_UNUSED(reply) + for (auto resource : resources) + emit discovered(resource); +} diff --git a/examples/coap/quickmulticastclient/qmlcoapmulticastclient.h b/examples/coap/quickmulticastclient/qmlcoapmulticastclient.h new file mode 100644 index 0000000..3dd91fc --- /dev/null +++ b/examples/coap/quickmulticastclient/qmlcoapmulticastclient.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the QtCoap module. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMLCOAPMULTICASTCLIENT_H +#define QMLCOAPMULTICASTCLIENT_H + +#include <QCoapClient> +#include <QCoapResource> + +class QmlCoapResource : public QCoapResource +{ + Q_GADGET + Q_PROPERTY(QString title READ title) + Q_PROPERTY(QString host READ hostStr) + Q_PROPERTY(QString path READ path) + +public: + QmlCoapResource() : QCoapResource() {} + QmlCoapResource(const QCoapResource &resource) + : QCoapResource(resource) {} + + QString hostStr() const { return host().toString(); } +}; +Q_DECLARE_METATYPE(QmlCoapResource) + +class QmlCoapMulticastClient : public QCoapClient +{ + Q_OBJECT + +public: + QmlCoapMulticastClient(QObject *parent = nullptr); + + Q_INVOKABLE void discover(const QString &host, int port, const QString &discoveryPath); + Q_INVOKABLE void discover(QtCoap::MulticastGroup group, int port, const QString &discoveryPath); + +Q_SIGNALS: + void discovered(const QmlCoapResource &resource); + void finished(QtCoap::Error error); + +public slots: + void onDiscovered(QCoapDiscoveryReply *reply, const QVector<QCoapResource> &resources); +}; + +#endif // QMLCOAPMULTICASTCLIENT_H diff --git a/examples/coap/quickmulticastclient/quickmulticastclient.pro b/examples/coap/quickmulticastclient/quickmulticastclient.pro new file mode 100644 index 0000000..e1e4558 --- /dev/null +++ b/examples/coap/quickmulticastclient/quickmulticastclient.pro @@ -0,0 +1,24 @@ +TEMPLATE = app + +QT += qml quick coap +CONFIG += c++11 + +DEFINES += QT_DEPRECATED_WARNINGS + +SOURCES += \ + main.cpp \ + qmlcoapmulticastclient.cpp + +RESOURCES += qml.qrc + +# Additional import path used to resolve QML modules in Qt Creator's code model +QML_IMPORT_PATH = + +# Additional import path used to resolve QML modules just for Qt Quick Designer +QML_DESIGNER_IMPORT_PATH = + +target.path = $$[QT_INSTALL_EXAMPLES]/coap/quickmulticastclient +INSTALLS += target + +HEADERS += \ + qmlcoapmulticastclient.h |