diff options
author | Ari Salmi <snowgrains@snowgrains.com> | 2017-07-15 00:37:31 +0300 |
---|---|---|
committer | Samuli Piippo <samuli.piippo@qt.io> | 2017-11-30 09:58:46 +0000 |
commit | d683d8b556f924a67aaa0012c417f9346b46ec1a (patch) | |
tree | 02936aa4c1d890299d7787de683b584c16f4d259 | |
parent | 8737866cee70b782ce862a450d0f8db1917be0df (diff) |
Initial import
Change-Id: I6a868ab4b9f418114e52f57c5b9db2b54f350a4f
Reviewed-by: Samuli Piippo <samuli.piippo@qt.io>
45 files changed, 6315 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..574d08e --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.DS_Store +build* +*.pro.* +.qmake.stash +*.autosave +Makefile.* +/mkspecs* +.moc/ +.pch/ +.obj/ diff --git a/.qmake.conf b/.qmake.conf new file mode 100644 index 0000000..42ad5e7 --- /dev/null +++ b/.qmake.conf @@ -0,0 +1,4 @@ +load(qt_build_config) + +MODULE_VERSION = 5.11.0 +CMAKE_MODULE_TESTS = - diff --git a/README.md b/README.md new file mode 100644 index 0000000..97fa634 --- /dev/null +++ b/README.md @@ -0,0 +1,242 @@ +QT CLOUD MESSAGING API INSTALLATION: + +1. To install with available backend add following to qmake script: + qmake "CONFIG += embedded-kaltiot" + or + qmake "CONFIG += firebase" + + e.g.: + qmake "CONFIG += embedded-kaltiot firebase" + make qmake_all + make + make install + +Google Firebase requirements: +2. Download and unzip google firebase c++ SDK: + https://firebase.google.com/docs/cpp/setup + +3. To use firebase as backend, define the following ENVIRONMENT variable + GOOGLE_FIREBASE_SDK = + and make it to point to your firebase sdk root + +Embedded-Kaltiot requirements: +4. To use in embedded Kaltiot backend: + 3.1. Register your app in + https://console.torqhub.io/signin + + 3.2. Download platform SDK from the console download page + + 3.3. Add environment variable to pointing to downloaded and unzipped SDK root: + KALTIOT_SDK = ../../../<yourappname>_RasperryPi_SDK_1.0.17 + + +5. Install first the QtCloudMessaging from command line with: + + qmake "CONFIG += embedded-kaltiot firebase" + make + make install + +6. Now you can use the QtCloudMessaging in your app with + + Just API wrapper (e.g. creating new service providers) + QT += cloudmessaging + + With Firebase backend: + QT += cloudmessagingfirebase + + With Embedded devices & Kaltiot + QT += cloudmessagingembeddedkaltiot + + See more from the example apps. + NOTE: Examples are in Github: + https://github.com/snowgrains/qtcloudmessaging-examples + +7. Usage basics: + + main.cpp: + + // Using QCloudMessaging: + #include <QtCloudMessaging> + #include <kaltiotdemo.h> + + // Depending on your backend provider, add: + + // For Embedded systems + #include <QtCloudMessagingEmbeddedKaltiot> + + // for Google firebase + #include <QCloudMessagingFirebaseProvider> + + #include <QGuiApplication> + #include <QQmlApplicationEngine> + #include <QQmlContext> + + int main(int argc, char *argv[]) + { + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + + //*** QTCLOUDMSG DEFINITIONS + QCloudMessaging *pushServices = new QCloudMessaging(); + + //***** For Kaltiot Embedded systems + QCloudMessagingEmbeddedKaltiotProvider *kaltiotPushService = new QCloudMessagingEmbeddedKaltiotProvider() + + // Provider based init parameters are given with QVariantMap + QVariantMap provider_params; + provider_params["API_KEY"] = "Your API key from the Kaltiot console for server communication"; + + // Creating name for provider which can be used cross your app. + pushServices->registerProvider("KaltiotService", kaltiotPushService, provider_params); + + QVariantMap client_params; + client_params["address"] = "IOTSensor1"; + client_params["version"] = "1.0"; + client_params["customer_id"] = "Kaltiot"; + + QVariantList channels; + channels.append("Temperatures"); + client_params["channels"] = channels; + + /*! Connected client for the device. + \param Service name "KaltiotService" + \param Client identifier name to be used inside the application + \param Parameters for the client specific for the provider API + */ + pushServices->connectClient("KaltiotService", "IOTSensor1", client_params); + + //***** OR For Firebase mobile systems: + QCloudMessagingFirebaseProvider *m_firebaseService = new QCloudMessagingFirebaseProvider(); + + QVariantMap provider_params; + + // Server API key is not recommended to store inside to the application code due security reasons. + // But if you do, make sure it is inside compiled C file or if you are doing a server side implementation with C++ & Qt. + // SERVER_API_KEY Is needed to be able to send topic messages from the client without Firebase application server. + + provider_params["SERVER_API_KEY"] = "Get your SERVER API KEY from the google firebase console"; + + // Registering the Google firebase service component. + pushServices->registerProvider("GoogleFireBase", m_firebaseService, provider_params); + + /*! Connected client is needed for mobile device. + \param Service name "GoogleFireBase" + \param Client identifier name to be used inside the demo application + \param Parameters for the client. No params for firebase client. + */ + pushServices->connectClient("GoogleFireBase", "MobileClient", QVariantMap()); + + //! Automatically subscribe to listen one example topic + pushServices->subscribeToChannel("ChatRoom", "GoogleFireBase", "MobileClient"); + + //*** END OF QTCLOUD MSG DEFINITIONS + + // these are needed for keeping the received RID in memory after restart (in Android) + QCoreApplication::setOrganizationName("MyOrganisation"); + QCoreApplication::setOrganizationDomain("MyOrganisation.com"); + QCoreApplication::setApplicationName("QtCloudMessagingDemo"); + + + // To Give QML the push service context: + engine.rootContext()->setContextProperty("pushServices", pushServices); + + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + + return app.exec(); + } + + main.qml: + + import QtQuick 2.6 + import QtQuick.Window 2.2 + + + Window { + visible: true + width: 640 + height: 480 + title: qsTr("Qt Cloud Messaging Demo") + + + // NOTIFICATIONS FROM THE ALL PROVIDERS: + Connections { + target:pushServices + onMessageReceived:{ + console.log("Message to " + providerId + " service to " + clientId + " client.") + console.log("Message: " + message) + + var msg_in_json = JSON.parse(decodeURI(message)); + + // Example to respond to embedded system request: + if (msg_in_json.command === "REQUESTING_TEMPERATURE") + embeddedPublishTemperatureToServer(msg_in_json.serverID, mydevicecommand.getTemperature()); + + // Or firebase the message itself is a container of the info. + updateGameNotification(message); + } + + // Own Uuid to be used or broadcasted to server. + onClientTokenReceived: { + + console.log("MY Uuid:"+rid) + + // Id this is server code: + serverUuid = rid; + + // Id this is client code: + clientUuid = rid; + + } + } + Component.onCompleted { + // In case android app and firebase sdk gets started fast and token is needed, it can be requested with: + clientUuid = pushServices.clientToken("GoogleFireBase", "MobileClient"); + } + + //***** EMBEDDED DEVICES + + // Function to send msg as server with Kaltiot provider to all clients as broadcast + property string serverUuid: "" + + function sendKaltiotEmbeddedServerMessage(command_msg, msg) { + + var payload = {command: command_msg, server_id : serverUuid}; // e.g. "REQUESTING_TEMPERATURE" + var payload_array = [{"payload_type": "STRING","payload": encodeURI(JSON.stringify(payload))}] + var p = "payload=" + JSON.stringify( payload_array ); + + pushServices.sendMessage(p, "KaltiotService", "", "", "Temperatures"); + } + + // Function to send temperature status message from the embedded client to Kaltiot server: + property string clientUuid :"" + + function embeddedPublishTemperatureToServer(serverUuid, temperature) { + var payload = {command: "TEMPERATURE_INFO", clientId: clientUuid} + var payload_array = [{"payload_type": "STRING","payload": encodeURI(JSON.stringify(payload))}] + var p = "payload=" + JSON.stringify( payload_array ); + + pushServices.sendMessage(p, "KaltiotService", "IOTSensor1", serverUuid,""); + } + //***** FIREBASE + // Function to post msg as a server and broadcast it to all clients in the same room + function sendFirebaseServerMessage(msg){ + var data = {"data": {"message": {"text": msg } }, + "notification": {"body": msg, "title": "Qt Cloud Messaging Chat"}} + + /*! + * \brief SendMessage + * \param msg Message as text which needs to be modified to the provider specific JSON. + * \param providerId Provider name specified at config + * \param localclientId clientId spefied at startup + * \param send_to_device Device Uuid (rid) to send for one known device + * \param send_to_channel Channel name to broadcast message to channel + * \return + */ + + pushServices.sendMessage(JSON.stringify(data), "GoogleFireBase", "MobileClient", "", "ChatRoom"); + } + } + + + diff --git a/dist/changes-1.0.0 b/dist/changes-1.0.0 new file mode 100644 index 0000000..75bd156 --- /dev/null +++ b/dist/changes-1.0.0 @@ -0,0 +1,23 @@ +Qt Cloud Messaging 1.0 + +Qt Cloud Messaging 1.0 is supported from Qt 5.x onwards. + +For more details on the features and fixes, refer to the online documentation +included in this distribution. The documentation is also available online: + + http://doc.qt.io/QtCloudMessaging + +General Improvements +-------------------- +Introducing new component for Qt + +API changes (source break) +-------------------------- + + +New features +------------ +- Introducing new component for Qt + +Fixed issues +------------ diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..9e3825b --- /dev/null +++ b/examples/README.md @@ -0,0 +1,8 @@ +QT CLOUD MESSAGING API EXAMPLES ARE IN GITHUB: + +Cloud messaging API examples are in the following address in github: +https://github.com/snowgrains/qtcloudmessaging-examples + +See more instructions from the README.md + + diff --git a/qtcloudmessaging.pro b/qtcloudmessaging.pro new file mode 100644 index 0000000..58c33f2 --- /dev/null +++ b/qtcloudmessaging.pro @@ -0,0 +1 @@ +load(qt_parts) diff --git a/src/cloudmessaging/cloudmessaging.pro b/src/cloudmessaging/cloudmessaging.pro new file mode 100644 index 0000000..7065843 --- /dev/null +++ b/src/cloudmessaging/cloudmessaging.pro @@ -0,0 +1,24 @@ +TARGET = QtCloudMessaging + +QT = core network + +QMAKE_DOCS = $$PWD/doc/qtcloudmessaging.qdocconf + +HEADERS += \ + $$PWD/qcloudmessaging.h \ + $$PWD/qcloudmessagingclient.h \ + $$PWD/qcloudmessagingprovider.h \ + $$PWD/qtcloudmessagingglobal.h \ + $$PWD/qcloudmessaging_p.h \ + $$PWD/qcloudmessagingclient_p.h \ + $$PWD/qcloudmessagingprovider_p.h \ + $$PWD/qcloudmessagingrestapi_p.h \ + $$PWD/qcloudmessagingrestapi.h + +SOURCES += \ + $$PWD/qcloudmessaging.cpp \ + $$PWD/qcloudmessagingclient.cpp \ + $$PWD/qcloudmessagingprovider.cpp \ + $$PWD/qcloudmessagingrestapi.cpp + +load(qt_module) diff --git a/src/cloudmessaging/doc/README.md b/src/cloudmessaging/doc/README.md new file mode 100644 index 0000000..50b4824 --- /dev/null +++ b/src/cloudmessaging/doc/README.md @@ -0,0 +1,11 @@ +QT CLOUD MESSAGING DOC GENERATION: + +define following exports in command prompt / terminal: +BUILDDIR="." +QT_VER="5.11" +QT_VERSION="5.11" +QT_VERSION_TAG="5.11" +QT_INSTALL_DOCS="<pathToQt>/Qt/Docs/Qt-5.9.2" + +Then run command: +<pathToQt>/Qt/5.9.2/<arch>/bin/qdoc qtcloudmessaging.qdocconf diff --git a/src/cloudmessaging/doc/qtcloudmessaging.qdocconf b/src/cloudmessaging/doc/qtcloudmessaging.qdocconf new file mode 100644 index 0000000..32dd078 --- /dev/null +++ b/src/cloudmessaging/doc/qtcloudmessaging.qdocconf @@ -0,0 +1,51 @@ +include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) + + +project = QtCloudMessaging +description = Qt Cloud Messaging Documentation +version = $QT_VERSION + +qhp.projects = QtCloudMessaging + +qhp.QtCloudMessaging.file = QtCloudMessaging.qhp +qhp.QtCloudMessaging.namespace = org.qt-project.qtcloudmessaging.$QT_VERSION_TAG +qhp.QtCloudMessaging.virtualFolder = qtcloudmessaging +qhp.QtCloudMessaging.indexTitle = Qt CloudMessaging +qhp.QtCloudMessaging.indexRoot = + +qhp.QtCloudMessaging.filterAttributes = qcloudmessaging $QT_VERSION qtrefdoc +qhp.QtCloudMessaging.customFilters.Qt.name = QtCloudMessaging $QT_VERSION +qhp.QtCloudMessaging.customFilters.Qt.filterAttributes = qcloudmessaging $QT_VERSION + +qhp.QtCloudMessaging.subprojects = classes +qhp.QtCloudMessaging.subprojects.classes.title = C++ Classes +qhp.QtCloudMessaging.subprojects.classes.indexTitle = Qt CloudMessaging C++ Classes +qhp.QtCloudMessaging.subprojects.classes.selectors = class fake:headerfile +qhp.QtCloudMessaging.subprojects.classes.sortPages = true + +# The outputdir variable specifies the directory +# where QDoc will put the generated documentation. + +outputdir = html + +# The headerdirs variable specifies the directories +# containing the header files associated +# with the .cpp source files used in the documentation. + +headerdirs += .. + +# The sourcedirs variable specifies the +# directories containing the .cpp or .qdoc +# files used in the documentation. + +sourcedirs += .. + +# The exampledirs variable specifies the directories containing +# the source code of the example files. + +#exampledirs += . + +# The imagedirs variable specifies the +# directories containing the images used in the documentation. + +#imagedirs += ./images diff --git a/src/cloudmessaging/qcloudmessaging.cpp b/src/cloudmessaging/qcloudmessaging.cpp new file mode 100644 index 0000000..3ecce6c --- /dev/null +++ b/src/cloudmessaging/qcloudmessaging.cpp @@ -0,0 +1,501 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcloudmessaging.h" +#include "qcloudmessaging_p.h" +#include <QString> + + +/*! + \class QCloudMessaging + \inmodule QtCloudMessaging + \since 5.11 + + \brief The QtCloudMessaging module implements Qt wrapper API for multiple + cloud messaging and cloud service providers. The QtCloudMessaging module + can be easily extended to support private clouds or existing cloud + providers. + + The QtCloudMessaging module currently has Google + Firebase Cloud Messaging and Kaltiot IoT push messaging backends to + get started with IoT or mobile cloud development. + + QCloudMessaging class enables registering of cloud messaging + provider backends and backend clients. + + Cloud messaging providers and clients implement virtual functions which + subscribe or unsubscribe to cloud messaging channels and receive or send + messages to servers and to other clients. + + \list + \li To create new cloud messaging service provider and client: + \list + \li Inherit the QCloudMessagingProvider class and implement the virtual + functions. + \li Inherit the QCloudMessagingClient class and implement the virtual + functions. + \endlist + \endlist + +*/ + +QT_BEGIN_NAMESPACE + +/*! + * \brief QCloudMessaging::QCloudMessaging + * QCloudMessaging constructor + * + * \param parent + * Parent is QObject + */ +QCloudMessaging::QCloudMessaging(QObject *parent) : + QObject(parent), d(new QCloudMessagingPrivate) +{ +} +/*! + * \brief QCloudMessaging::~QCloudMessaging + */ +QCloudMessaging::~QCloudMessaging() +{ +} + +/*! + * \brief registerProvider + * Registers the service provider that handles service clients and can be used + * for server side development. + * + * \param providerId + * Provider identification string that is defined by the user when using the + * API. + * + * \param provider + * Use case specific provider object that can handle the communication as a + * server and can have multiple internal and external clients. + * + * \param parameters + * Provider specific parameters in a variant map. + * + * \return + * true if register succeeds, false if fails. + */ +bool QCloudMessaging::registerProvider(const QString &providerId, + QCloudMessagingProvider *provider, + const QVariantMap ¶meters) +{ + bool return_value = false; + // If this is duplicate service name + if (!d->m_cloudProviders.contains(providerId)) { + d->m_cloudProviders.insert(providerId, provider); + + connect(provider, &QCloudMessagingProvider::messageReceived, + this, &QCloudMessaging::messageReceived); + + connect(provider, &QCloudMessagingProvider::serviceStateUpdated, + this, &QCloudMessaging::serviceStateUpdated); + + connect(provider, &QCloudMessagingProvider::remoteClientsReceived, + this, &QCloudMessaging::remoteClientsReceived); + + connect(provider, &QCloudMessagingProvider::clientTokenReceived, + this, &QCloudMessaging::clientTokenReceived); + + return_value = d->m_cloudProviders[providerId]-> + registerProvider(providerId,parameters); + } else { + return_value = d->m_cloudProviders[providerId]->getServiceState(); + } + + return return_value; +} + +/*! + * \brief connectClient + * Attaches the client into the provider + * + * \param providerId + * Provider identification string that is defined by the user when using the + * API + * + * \param clientId + * Mobile or IoT client identification string (defined by user) added for the + * provider + * + * \param parameters + * Client specific parameters in a variant map. + * + * \return + * return given ClientId when succeeds, empty string if not. + * + */ +QString QCloudMessaging::connectClient(const QString &providerId, + const QString &clientId, + const QVariantMap ¶meters) +{ + if (d->m_cloudProviders.contains(providerId)) + return d->m_cloudProviders[providerId]->connectClient(clientId, + parameters); + + return QString(); +} + +/*! + * \brief sendMessage + * Sends a message to one single client or or to a subscribed channel + * + * \param msg + * Service specific message. Usually JSON string. + * + * \param providerId + * Provider identification string that is defined by the user when using + * the API + * + * \param clientId + * Mobile or IoT client identification string (defined by user) added for + * the provider + * + * \param clientToken + * By providing client token, message is targeted straight to client + * + * \param channel + * Channel name if broadcasting the message to channel + * + * \return + * return true when succeeds, false otherwise. + */ +bool QCloudMessaging::sendMessage(const QByteArray &msg, + const QString &providerId, + const QString &clientId, + const QString &clientToken, + const QString &channel) +{ + + if (d->m_cloudProviders.contains(providerId)) + return d->m_cloudProviders[providerId]->sendMessage(msg, + clientId, + clientToken, + channel); + + return false; +} + + +/*! + * \brief disconnectClient + * Disconnects the client from the provider + * + * \param providerId + * Provider identification string that is defined by the user when using the + * API + * + * \param clientId + * Mobile or IoT client identification string (defined by user) added for the + * provider + * + * \param parameters + * Client specific parameters in a variant map. + */ +void QCloudMessaging::disconnectClient(const QString &providerId, + const QString &clientId, + const QVariantMap ¶meters) +{ + if (d->m_cloudProviders.contains(providerId)) + d->m_cloudProviders[providerId]->disconnectClient(clientId, + parameters); +} + +/*! + * \brief removeClient + * Removes client from the provider + * + * \param providerId + * Provider identification string that is defined by the user when using the + * API + * + * \param clientId + * Mobile or IoT client identification string (defined by user) added for the + * provider + */ +void QCloudMessaging::removeClient(const QString &providerId, + const QString &clientId) +{ + if (d->m_cloudProviders.contains(providerId)) + d->m_cloudProviders[providerId]->removeClient(clientId); + +} + +/*! + * \brief deRegisterProvider + * Closes down the provider and disconnects clients. + * + * \param providerId + * Povider identification string that is defined by the user when using the + * API + */ +void QCloudMessaging::deregisterProvider(const QString &providerId) +{ + if (d->m_cloudProviders.contains(providerId)) { + disconnect(d->m_cloudProviders[providerId]); + + d->m_cloudProviders[providerId]->deregisterProvider(); + d->m_cloudProviders.remove(providerId); + + } +} + +/*! + * \brief localClients + * If system has multiple clients connected at the same app process, one can + * request the + * list of available clientIds from the provider class. + * + * \param providerId + * Provider identification string that is defined by the user when using the + * API + * + * \return + * List of ClientIds as QStringList. + */ +const QStringList QCloudMessaging::localClients(const QString &providerId) +{ + if (d->m_cloudProviders.contains(providerId)) + return d->m_cloudProviders[providerId]->clients()->keys(); + + return QStringList(); +} + +/*! + * \brief requestRemoteClients + * Uses provider rest api interface to request all the remote clients + * connected to provider service. + * This can be used e.g. in server implementation or if creating + * client dashboard etc. + * + * \param providerId + * Provider identification string that is defined by the user when + * using the API + * + * \return + * true if sending request via rest api succeeds, fail if not. + */ +bool QCloudMessaging::requestRemoteClients(const QString &providerId) +{ + if (d->m_cloudProviders.contains(providerId)) { + return d->m_cloudProviders[providerId]->remoteClients(); + } + + return false; +} + +/*! + * \brief clientToken + * Gets client token (uuid / rid received from the provider services) + * + * \param providerI + * Provider identification string that is defined by the user when using + * the API + * + * \param clientId + * Mobile or IoT client identification string (defined by user) added for + * the provider + * + * \return + * If found returns client token as QString. Returns empty QString otherwise. + */ +QString QCloudMessaging::clientToken(const QString &providerId, + const QString &clientId) +{ + if (d->m_cloudProviders.contains(providerId)) + return d->m_cloudProviders[providerId]->clientToken(clientId); + + return QString(); +} + +/*! + * \brief setClientToken + * Sets the client token for the client. + * This can be used in case of client + * token is received otherwise or defined by + * API user separately. + * + * \param providerId + * Provider identification string that is defined by the user when using the + * API + * + * \param clientId + * Mobile or IoT client identification string (defined by user) added for the + * provider + * + * \param token + * Token value as string + */ +void QCloudMessaging::setClientToken(const QString &providerId, + const QString &clientId, + const QString &token) +{ + if (d->m_cloudProviders.contains(providerId)) + return d->m_cloudProviders[providerId]-> + client(clientId)->setClientToken(token); +} + +/*! + * \brief QCloudMessaging::subscribeToChannel + * Subscribing the client to the channel + * + * \param channel + * Channel name as string, cannot be empty + * + * \param providerId + * Provider identification string that is defined by the user when using the API + * + * \param clientId + * Mobile or IoT client identification string (defined by user) added for + * the provider + * + * \return + * true if succeeds, false if not. + */ +bool QCloudMessaging::subscribeToChannel(const QString &channel, + const QString &providerId, + const QString &clientId) +{ + if (!d->m_cloudProviders.contains(providerId)) + return false; + + if (!clientId.isEmpty()) + { + return d->m_cloudProviders[providerId]->client(clientId)-> + subscribeToChannel(channel); + } else + { + return d->m_cloudProviders[providerId]->subscribeToChannel(channel, + clientId); + } +} + +/*! + * \brief unsubscribeFromChannel + * Unsubscribing the client from the channel + * + * \param channel + * Channel name as string, cannot be empty + * + * \param providerId + * Provider identification string that is defined by the user when using the + * API + * + * \param clientId + * Mobile or IoT client identification string (defined by user) added for the + * provider + * + * \return + * true if succeeds, false if not. + */ +bool QCloudMessaging::unsubscribeFromChannel(const QString &channel, + const QString &providerId, + const QString &clientId) +{ + if (!d->m_cloudProviders.contains(providerId)) + return false; + + if (!clientId.isEmpty()) + { + return d->m_cloudProviders[providerId]->client(clientId)-> + unsubscribeFromChannel(channel); + } else + { + return d->m_cloudProviders[providerId]->unsubscribeFromChannel(channel, + clientId); + } +} + +/*! + * \brief flushMessageQueue + * When receiving push messages they can be stored by clients internally. + * This function gives developers possibility to do flush commnand for them . + * + * \param providerId + * Provider identification string that is defined by the user when using the + * API + * + * \return + * true if succeeds, false if not + */ +void QCloudMessaging::flushMessageQueue(const QString &providerId) +{ + if (d->m_cloudProviders.contains(providerId)) + d->m_cloudProviders[providerId]->flushMessageQueue(); +} + +// Signals documentation +/*! + \fn QCloudMessaging::clientTokenReceived(const QString &token) + This signal is triggered when connected gets the client + token from the service provider. + + \param token + Received token as a QString. + Token is unique identification value used for straight communication + and identification with the client. +*/ + +/*! + \fn QCloudMessaging::messageReceived(const QString &providerId, + const QString &clientId, + const QByteArray &message) + This signal is triggered when a message is received from the network to client. + + \param providerId + Receiving Provider identification string + + \param clientId + Receiving clientId string + + \param message + Received message as QByteArray. Message is service specific. +*/ + +/*! + \fn QCloudMessaging::remoteClientsReceived(const QString &clients) + This signal is triggered when the return value for requestRemoteClients + function is is received. + \param response + Response data is based on the service and can be e.g. a list + of client tokens in QString format. +*/ + +/*! + \fn QCloudMessaging::serviceStateUpdated(int state) + This signal is triggered when the service provider registered + state has changed. + + \param state + State can be one of the enums from the QCloudMessagingProvider + +*/ + +QT_END_NAMESPACE diff --git a/src/cloudmessaging/qcloudmessaging.h b/src/cloudmessaging/qcloudmessaging.h new file mode 100644 index 0000000..cbd5b95 --- /dev/null +++ b/src/cloudmessaging/qcloudmessaging.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCLOUDMESSAGING_H +#define QTCLOUDMESSAGING_H + +#include <QtCloudMessaging/qtcloudmessagingglobal.h> +#include <QtCloudMessaging/qcloudmessagingprovider.h> +#include <QObject> +#include <QVariantMap> +#include <QScopedPointer> + +QT_BEGIN_NAMESPACE + +/*! + * \class QCloudMessaging + * \brief The QCloudMessaging class + * + * This is the Qt Cloud Messaging Class. + */ +class QCloudMessagingPrivate; + + +class Q_CLOUDMESSAGING_EXPORT QCloudMessaging : public QObject +{ + Q_OBJECT + +public: + + explicit QCloudMessaging(QObject *parent = nullptr); + ~QCloudMessaging(); + + Q_INVOKABLE bool registerProvider(const QString &providerId, + QCloudMessagingProvider *provider, + const QVariantMap ¶meters = QVariantMap()); + + Q_INVOKABLE void deregisterProvider(const QString &providerId); + + Q_INVOKABLE QString connectClient(const QString &providerId, + const QString &clientId, + const QVariantMap ¶meters = + QVariantMap()); + + Q_INVOKABLE void disconnectClient(const QString &providerId, + const QString &clientId, + const QVariantMap ¶meters = + QVariantMap()); + + Q_INVOKABLE const QStringList localClients(const QString &providerId); + + Q_INVOKABLE bool requestRemoteClients(const QString &providerId); + + Q_INVOKABLE void removeClient(const QString &providerId, + const QString &clientId); + + Q_INVOKABLE QString clientToken(const QString &providerId, + const QString &clientId); + + Q_INVOKABLE void setClientToken(const QString &providerId, + const QString &clientId, + const QString &token); + + Q_INVOKABLE bool sendMessage(const QByteArray &msg, + const QString &providerId = QString(), + const QString &clientId = QString(), + const QString &clientToken = QString(), + const QString &channel = QString()) ; + + Q_INVOKABLE bool subscribeToChannel(const QString &channel, + const QString &providerId = QString(), + const QString &clientId = QString()); + + Q_INVOKABLE bool unsubscribeFromChannel(const QString &channel, + const QString &providerId = QString(), + const QString &clientId = QString()); + + Q_INVOKABLE void flushMessageQueue(const QString &providerId); + +Q_SIGNALS: + void clientTokenReceived(const QString &token); + + void messageReceived(const QString &providerId, + const QString &clientId, + const QByteArray &message); + + void remoteClientsReceived(const QString &clients); + + void serviceStateUpdated(int state); + +private: + QScopedPointer<QCloudMessagingPrivate> d; + +}; + +QT_END_NAMESPACE + +#endif // QTCLOUDMESSAGING_H diff --git a/src/cloudmessaging/qcloudmessaging_p.h b/src/cloudmessaging/qcloudmessaging_p.h new file mode 100644 index 0000000..e7b26c0 --- /dev/null +++ b/src/cloudmessaging/qcloudmessaging_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLOUDMESSAGING_P_H +#define QCLOUDMESSAGING_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +#include <QtCloudMessaging/qtcloudmessagingglobal.h> +#include <QMap> +#include <QMapIterator> + +QT_BEGIN_NAMESPACE + +class QCloudMessagingProvider; + +class QCloudMessagingPrivate +{ + +public: + QCloudMessagingPrivate() + : m_serviceState(0) + { + } + + ~QCloudMessagingPrivate() + { + m_serviceState = 0; + + // To verify that all providers and clients are removed + // without memory leaks + QMapIterator<QString, QCloudMessagingProvider *> i(m_cloudProviders); + while (i.hasNext()) { + i.next(); + m_cloudProviders[i.key()]->deregisterProvider(); + m_cloudProviders.remove(i.key()); + } + } + + int m_serviceState; + QMap<QString, QCloudMessagingProvider *> m_cloudProviders; + +}; + +QT_END_NAMESPACE + +#endif // QCLOUDMESSAGING_P_H diff --git a/src/cloudmessaging/qcloudmessagingclient.cpp b/src/cloudmessaging/qcloudmessagingclient.cpp new file mode 100644 index 0000000..e2c6685 --- /dev/null +++ b/src/cloudmessaging/qcloudmessagingclient.cpp @@ -0,0 +1,333 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcloudmessagingclient.h" +#include "qcloudmessagingclient_p.h" + +/*! + \class QCloudMessagingClient + \inmodule QtCloudMessaging + \since 5.11 + + \brief The QCloudMessagingClient class is a single IoT/embedded or mobile device + providing way to received and send messages either by broadcasting or + by direct connect to other client with known token. + + Implementing specific cloud messaging service client needs inherit this + QCloudMessagingClient class and implement the virtual functions defined in the + header. + +*/ + +QT_BEGIN_NAMESPACE + +/*! + * \brief QCloudMessagingClient::QCloudMessagingClient + * QCloudMessagingClient constructor + * + * \param parent + * Parent is QObject + */ +QCloudMessagingClient::QCloudMessagingClient(QObject *parent) : + QObject(parent), + d(new QCloudMessagingClientPrivate) +{ +} + +/*! + * \brief QCloudMessagingClient::~QCloudMessagingClient + * Desctructor + */ +QCloudMessagingClient::~QCloudMessagingClient() +{ + disconnectClient(); +} + +/*! + * \brief QCloudMessagingClient::connectClient + * Attaches the client into the provider. This is virtual function + * and should be re-implemented in the inheritance for connecting + * the client to real service. + * + * \param clientId + * Mobile or IoT client identification string (defined by user) added for the + * provider + * + * \param parameters + * Client specific parameters in a variant map. + * + * \return + * return given ClientId when successful, empty string if not. + * + */ +QString QCloudMessagingClient::connectClient(const QString &clientId, + const QVariantMap ¶meters) +{ + d->m_clientId = clientId; + d->m_clientState = QtCloudMessagingClientConnecting; + d->m_client_parameters = parameters; + + return QString(); +} + +/*! + * \brief QCloudMessagingClient::disconnectClient + * Virtual function to disconnect the client from the service. + * + * \return + * returns the client specific state as integer + */ +void QCloudMessagingClient::disconnectClient() +{ + d->m_clientState = QtCloudMessagingClientDisconnecting; +} + +/*! + * \brief QCloudMessagingClient::setClientState + * Sets the client state. This is virtual function and can be + * re-implemented in the inheritance + * + * \param state + * Setting client specific state as integer. + */ +void QCloudMessagingClient::setClientState(int state) +{ + d->m_clientState = state; +} + +/*! + * \brief QCloudMessagingClient::clientState + * Gets the client specific state + * + * \return + * Returns clients specific state value as integer. + */ +int QCloudMessagingClient::clientState() +{ + return (CloudMessagingClientState) d->m_clientState; +} + +/*! + * \brief QCloudMessagingClient::clientId + * Gets the client id. + * + * \return + * Returns client id as QString + */ +QString QCloudMessagingClient::clientId() +{ + return d->m_clientId; +} + +/*! + * \brief QCloudMessagingClient::providerId + * Gets the client's service provider id. + * + * \return + * Returns the provider id as QString. + */ +QString QCloudMessagingClient::providerId() +{ + return d->m_providerId; +} + +/*! + * \brief QCloudMessagingClient::setClientId + * Sets the client id + * + * \param clientid + * Client id as QString + * + * \return + * Returns new client id as QString + */ +void QCloudMessagingClient::setClientId(const QString &clientid) +{ + d->m_clientId = clientid; +} + +/*! + * \brief QCloudMessagingClient::setProviderId + * Gets the client's service provider id. + * + * \return + * Returns new provider id as QString. + */ +void QCloudMessagingClient::setProviderId(const QString &providerId) +{ + d->m_providerId = providerId; +} + +/*! + * \brief QCloudMessagingClient::clientParameters + * Gets the client parameters + * + * \return + * Returns client parameters as QVariantMap + */ +QVariantMap QCloudMessagingClient::clientParameters() +{ + return d->m_client_parameters; +} + +// Pure Virtual functions documentation + +/*! + \fn QCloudMessagingClient::flushMessageQueue() + When receiving push messages they can be stored by clients internally. + This function gives developers possibility to do flush commnand for them. + + This is pure virtual function and needs to be implemented in the + inheritance. + + \return + return true when successful, false otherwise. +*/ +/*! + \fn QCloudMessagingClient::sendMessage( + const QByteArray &msg, + const QString &clientToken = QString(), + const QString &channel = QString()) + Sends a message to one single client or to subscribed channel. + This is pure virtual function and needs to be implemented in the inheritance. + + \param msg + Message as string which is interpreted to the service specific message + type e.g. json + + \param clientToken + By providing client token, message is targeted straight to client + + \param channel + Channel name if broadcasting the message to channel + + \return + return true when successful, false otherwise. +*/ + +/*! + \fn QCloudMessagingClient::setClientToken(const QString &token) + Sets the client token for the client. + This can be used in case of client + token is received otherwise or defined by + API user separately. + + + \param token + Token value as string +*/ + +/*! + \fn QCloudMessagingClient::clientToken() + Gets client token (uuid / rid received from the provider services) + + \return + If found returns client token as QString. Returns empty QString otherwise. +*/ + +/*! + \fn QCloudMessagingClient::subscribeToChannel( + const QString &channel) + Subscribes client to broadcast channel of the provider service. + This is pure virtual function and needs to be implemented in the + inheritance. + + \param channnel + Channel name as QString + + \return + return true when successful, false otherwise. +*/ + +/*! + \fn QCloudMessagingClient::unsubscribeFromChannel( + const QString &channel) + Unsubscribes client from the broadcast channel of the provider service. + This is pure virtual function and needs to be implemented in the + inheritance. + + \param channnel + Channel name as QString + + \return + return true when successful, false otherwise. +*/ + +// Signals documentation +/*! + \fn QCloudMessagingClient::clientStateChanged( + const QString &clientId, + int state) + This signal is triggered when the client state has changed + + \param clientId + Client idenfitication string + + \param state + Client State can be either enum from QCloudMessagingClient::CloudMessagingClientState + or it can be client backend specific state. + +*/ + +/*! + \fn QCloudMessagingClient::messageReceived(const QString &clientId, + const QByteArray &message) + This signal is triggered when a message is received from the network to client. + + \param clientId + Receiving clientId string + + \param message + Received message as QByteArray. Message content is service specific. +*/ + +/*! + \fn QCloudMessagingClient::clientTokenReceived(const QString &token) + This signal is triggered when connected gets the client + token from the service provider. + + \param token + Received token as a QString. + Token is unique identification value used for straight communication + and identification with the client. +*/ + +// Enums +/*! + \enum QCloudMessagingClient::CloudMessagingClientState + + This enum type describes types of QCloudMessagingClient connection states. + + \value QtCloudMessgingClientDisconnected Client is disconnected. + \value QtCloudMessagingClientConnecting Client connection started. + \value QtCloudMessagingClientDisconnecting Client disconnection started. + \value QtCloudMessagingClientOffline Client is connected but offline. + \value QtCloudMessagingClientOnline Client is connected and online. + +*/ +QT_END_NAMESPACE diff --git a/src/cloudmessaging/qcloudmessagingclient.h b/src/cloudmessaging/qcloudmessagingclient.h new file mode 100644 index 0000000..35a6f39 --- /dev/null +++ b/src/cloudmessaging/qcloudmessagingclient.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCLOUDMESSAGINGCLIENT_H +#define QTCLOUDMESSAGINGCLIENT_H + +#include <QtCloudMessaging/qtcloudmessagingglobal.h> + +#include <QObject> +#include <QVariantMap> +#include <QString> +#include <QScopedPointer> + +QT_BEGIN_NAMESPACE + +class QCloudMessagingClientPrivate; + +class Q_CLOUDMESSAGING_EXPORT QCloudMessagingClient : public QObject +{ + Q_OBJECT + +public: + + enum CloudMessagingClientState { + QtCloudMessgingClientDisconnected = 0, + QtCloudMessagingClientConnecting, + QtCloudMessagingClientDisconnecting, + QtCloudMessagingClientOffline, + QtCloudMessagingClientOnline + }; + Q_ENUM(CloudMessagingClientState) + + explicit QCloudMessagingClient(QObject *parent = nullptr); + + virtual ~QCloudMessagingClient(); + + virtual QString connectClient( + const QString &clientId, + const QVariantMap ¶meters = QVariantMap()); + + virtual void disconnectClient(); + + virtual void cloudMessageReceived(const QString &client, + const QByteArray &message) = 0; + + virtual QString clientToken() = 0; + + virtual void setClientToken(const QString &token) = 0; + + virtual bool sendMessage( + const QByteArray &msg, + const QString &clientToken = QString(), + const QString &channel = QString()) = 0; + + virtual bool flushMessageQueue() = 0; + + virtual bool subscribeToChannel(const QString &channel) = 0; + + virtual bool unsubscribeFromChannel(const QString &channel) = 0; + + void setClientState(int state); + + int clientState(); + + QString clientId(); + + QString providerId(); + + void setClientId(const QString &clientid); + + void setProviderId(const QString &providerId); + + QVariantMap clientParameters(); + +Q_SIGNALS: + void clientStateChanged(const QString &clientId, int state); + + void messageReceived(const QString &clientId, const QByteArray &msg); + + void clientTokenReceived(const QString &token); + +private: + + QScopedPointer<QCloudMessagingClientPrivate> d; + +}; + +QT_END_NAMESPACE + +#endif // QTCLOUDMESSAGINGCLIENT_H diff --git a/src/cloudmessaging/qcloudmessagingclient_p.h b/src/cloudmessaging/qcloudmessagingclient_p.h new file mode 100644 index 0000000..a1d0b0b --- /dev/null +++ b/src/cloudmessaging/qcloudmessagingclient_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLOUDMESSAGINGCLIENT_P_H +#define QCLOUDMESSAGINGCLIENT_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QVariantMap> +#include <QtCloudMessaging/qtcloudmessagingglobal.h> + +QT_BEGIN_NAMESPACE + + +class QCloudMessagingClient; + +class QCloudMessagingClientPrivate +{ +public: + QCloudMessagingClientPrivate() + : m_clientState(0) + { + } + + ~QCloudMessagingClientPrivate() = default; + + QString m_clientId; + QString m_providerId; + int m_clientState; + QVariantMap m_client_parameters; + +}; + +QT_END_NAMESPACE + +#endif // QCLOUDMESSAGINGCLIENT_P_H diff --git a/src/cloudmessaging/qcloudmessagingprovider.cpp b/src/cloudmessaging/qcloudmessagingprovider.cpp new file mode 100644 index 0000000..0c276d4 --- /dev/null +++ b/src/cloudmessaging/qcloudmessagingprovider.cpp @@ -0,0 +1,543 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcloudmessagingprovider.h" +#include "qcloudmessagingprovider_p.h" +#include <QMapIterator> + +/*! + \class QCloudMessagingProvider + \inmodule QtCloudMessaging + \since 5.11 + + \brief The QCloudMessagingProvider class provides the functions to register + multiple cloud messaging providers and clients. CloudMessagingProvider class + manages locally registered cloud messaging clients and provides the + status of the services. + + To implement specific cloud messaging provider functionality, the inherit of this + QCloudMessagingProvider class is needed. Inherited class also needs to implement the + QCloudMessagingProvider virtual functions. + +*/ + +QT_BEGIN_NAMESPACE + +/*! + * \brief QCloudMessagingProvider::QCloudMessagingProvider + * Class constructor + * + * \param parent + * QObject parent + */ +QCloudMessagingProvider::QCloudMessagingProvider(QObject *parent) : + QObject(parent), + d(new QCloudMessagingProviderPrivate) +{ +} + +/*! + * \brief QCloudMessagingProvider::~QCloudMessagingProvider + * Class descructor + */ +QCloudMessagingProvider::~QCloudMessagingProvider() +{ +} + +/*! + * \brief QCloudMessagingProvider::registerProvider + * Registers the service provider that handles service clients and can be used + * for server side development. + * This is pure virtual function which needs to be implemented by the provider + * class inheritance. + * + * \param providerId + * Provider identification string that is defined by the user when using the + * API + * + * \param parameters + * Provider specific parameters in the variant map. + * + * \return + */ +bool QCloudMessagingProvider::registerProvider(const QString &providerId, + const QVariantMap ¶meters) +{ + Q_UNUSED(parameters); + + d->m_providerId = providerId; + + d->m_serviceState = CloudMessagingProviderState::QtCloudMessagingProviderRegistering; + emit serviceStateUpdated(d->m_serviceState); + return true; +} + +/*! + * \brief QCloudMessagingProvider::connectClientToProvider + * Function to create necessary signal connections between the new service client + * and calls serviceClients connectClient virtual function. + * This function should be called from the inherited class connectClient function. + * + * Example code: + * \code + * QCloudMessagingEmbeddedKaltiotClient *serviceClient = new QCloudMessagingEmbeddedKaltiotClient(); + * QString retval = connectClientToProvider(clientId, parameters, serviceClient); + * \endcode + * + * \param clientId + * Client id as QString + * + * \param parameters + * Client specific parameters in a variant map. + * + * \param serviceClient + * Service client instance of inheritance of QCloudMessagingClient class + * + * \return + * Returns clientId as QString if succesfull, empty QString otherwise. + */ +QString QCloudMessagingProvider::connectClientToProvider(const QString &clientId, + const QVariantMap ¶meters, + QCloudMessagingClient *serviceClient) +{ + if (!d->m_providerId.isEmpty()) { + d->m_provider_parameters = parameters; + if (!clientId.isEmpty()) { + + connect(serviceClient, &QCloudMessagingClient::messageReceived, + this, &QCloudMessagingProvider::messageReceivedSlot); + + connect(serviceClient, &QCloudMessagingClient::clientTokenReceived, + this, &QCloudMessagingProvider::clientTokenReceived); + + connect(serviceClient, &QCloudMessagingClient::clientStateChanged, + this, &QCloudMessagingProvider::clientStateChanged); + + serviceClient->connectClient(clientId, parameters); + + d->m_QtCloudMessagingClients.insert(clientId, serviceClient); + + return clientId; + } + } + + return QString(); +} + +/*! + * \brief QCloudMessagingProvider::messageReceivedSlot + * This slot is executed when new message is received from the service provider. + * + * \param clientId + * Client id receiving the message + * + * \param message + * Message content as QByteArray + * + */ +void QCloudMessagingProvider::messageReceivedSlot(const QString &clientId, const QByteArray &message) +{ + emit messageReceived(providerId(), clientId, message); +} + +/*! + * \brief QCloudMessagingProvider::disconnectClient + * \param clientId + * \param parameters + * \return + */ +void QCloudMessagingProvider::disconnectClient(const QString &clientId, + const QVariantMap ¶meters) +{ + Q_UNUSED(parameters); + + if (!d->m_providerId.isEmpty() && d->m_QtCloudMessagingClients[clientId]) { + QCloudMessagingClient *client = d->m_QtCloudMessagingClients[clientId]; + + // Disconnect connections for the client + disconnect(client); + + d->m_QtCloudMessagingClients[clientId]->disconnectClient(); + } + +} + +/*! + * \brief QCloudMessagingProvider::removeClient + * \param clientId + * \return + */ +bool QCloudMessagingProvider::removeClient(const QString &clientId) +{ + if (!d->m_providerId.isEmpty() && d->m_QtCloudMessagingClients[clientId]) { + + disconnectClient(clientId); + d->m_QtCloudMessagingClients.remove(clientId); + + return true; + } + + return false; +} + +/*! + * \brief QCloudMessagingProvider::deregisterProvider + * Function to deregistering the service provider. This + * function automatically removes clients registered to the provider. + * This is virtual function and can be implemented by the provider + * class inheritance. + * + * \return + */ +void QCloudMessagingProvider::deregisterProvider() +{ + if (d->m_QtCloudMessagingClients.count()) { + + QMapIterator<QString, QCloudMessagingClient *> i(d->m_QtCloudMessagingClients); + + while (i.hasNext()) { + i.next(); + removeClient(i.key()); + } + + d->m_serviceState = CloudMessagingProviderState::QtCloudMessagingProviderNotRegistered; + emit serviceStateUpdated(d->m_serviceState); + } +} + +/*! + * \brief QCloudMessagingProvider::flushMessageQueue + * This function calls the service provider to clear clients message buffers. + * Client flushMessageQueue is virtualized for client specific usages. + * + * \return + * false if no clients found, true if also clients removed. + */ +bool QCloudMessagingProvider::flushMessageQueue() +{ + if (d->m_QtCloudMessagingClients.count()) { + QMapIterator<QString, QCloudMessagingClient *> i(d->m_QtCloudMessagingClients); + while (i.hasNext()) { + i.next(); + d->m_QtCloudMessagingClients[i.key()]->flushMessageQueue(); + } + return true; + } + return false; +} + +/*! + * \brief QCloudMessagingProvider::clientToken + * Get the clientToken from the client + * + * \param clientId + * ClientId as string. + * + * \return + * Return clientId token as string if found. Empty string if client not found. + */ +QString QCloudMessagingProvider::clientToken(const QString &clientId) +{ + if (!d->m_providerId.isEmpty() && d->m_QtCloudMessagingClients[clientId]) { + return d->m_QtCloudMessagingClients[clientId]->clientToken(); + + } + return QString(); +} + +/*! + * \brief QCloudMessagingProvider::clients + * Get client instances as key value pairs, where clientId is the key. + * + * \return + * Client instances as key value pairs + */ +QMap <QString, QCloudMessagingClient *> *QCloudMessagingProvider::clients() +{ + return &d->m_QtCloudMessagingClients; +} + +/*! + * \brief QCloudMessagingProvider::client + * Finds the client instance based on the clientId + * + * \param clientId + * ClientId as QString + * + * \return + * Client instance if found, nullptr if not found. + */ +QCloudMessagingClient *QCloudMessagingProvider::client(const QString &clientId) +{ + if (d->m_QtCloudMessagingClients.find(clientId) == d->m_QtCloudMessagingClients.end()) + return nullptr; + + return d->m_QtCloudMessagingClients[clientId]; +} + +/*! + * \brief QCloudMessagingProvider::setServiceState + * Sets the provider service state + * + * \param state + * State value from the enum CloudMessagingProviderState. + * + * \return + * Returns the given state back. + */ +QCloudMessagingProvider::CloudMessagingProviderState QCloudMessagingProvider:: + setServiceState(QCloudMessagingProvider::CloudMessagingProviderState state) +{ + d->m_serviceState = state; + return (QCloudMessagingProvider::CloudMessagingProviderState)d->m_serviceState; +} + +/*! + * \brief QCloudMessagingProvider::getServiceState + * Gets the service provider state + * + * \return + * Return the current state value as CloudMessagingProviderState. + */ +QCloudMessagingProvider::CloudMessagingProviderState QCloudMessagingProvider::getServiceState() +{ + return (QCloudMessagingProvider::CloudMessagingProviderState) d->m_serviceState; +} + +/*! + * \brief QCloudMessagingProvider::providerId + * Gets the service provider Id + * + * \return + * return service provider id as a QString + */ +QString QCloudMessagingProvider::providerId() +{ + return d->m_providerId; +} + +/*! + * \brief QCloudMessagingProvider::setProviderId + * Sets the service provider Id + * + * \param providerId + * Service provider id as QString + */ +void QCloudMessagingProvider::setProviderId(const QString &providerId) +{ + d->m_providerId = providerId; +} + +// Pure Virtual functions documentation +/*! + \fn QCloudMessagingProvider::connectClient( + const QString &clientId, + const QVariantMap ¶meters = QVariantMap()) + Connects the client to provider. This is pure virtual function + and needs to be implemented in the inheritance. + + \param clientId + Mobile or IoT client identification string (defined by user) added for the + provider + + \param parameter + Client specific parameters in a variant map. + + \return + return given ClientID when successful, empty string otherwise. +*/ +/*! + \fn QCloudMessagingProvider::disconnectClient( + const QString &clientId, + const QVariantMap ¶meters = QVariantMap()) + Disconnects the client from the provider. This is pure virtual function + and needs to be implemented in the inheritance. + + \param clientId + Mobile or IoT client identification string (defined by user) added for the + provider + + \param parameter + Client specific parameters in a variant map. + + \return + return true when successful, false otherwise. +*/ + +/*! + \fn QCloudMessagingProvider::sendMessage( + const QByteArray &msg, + const QString &clientId = QString(), + const QString &clientToken = QString(), + const QString &channel = QString()) + Sends a message to one single client or to subscribed channel. + This is pure virtual function and needs to be implemented in the inheritance. + + \param msg + Message as string which is interpreted to the service specific message + type e.g. json + + \param clientId + Mobile or IoT client identification string (defined by user) added for the + provider + + \param clientToken + By providing client token, message is targeted straight to client + + \param channel + Channel name if broadcasting the message to channel + + \return + return true when successful, false otherwise. +*/ + +/*! + \fn QCloudMessagingProvider::subscribeToChannel( + const QString &channel, + const QString &clientId = QString()) + Subscribes client to broadcast channel of the provider service. + This is pure virtual function and needs to be implemented in the + inheritance. + + \param channnel + Channel name as QString + + \param clientId + Client id as QString + + \return + return true when successful, false otherwise. +*/ + +/*! + \fn QCloudMessagingProvider::unsubscribeFromChannel( + const QString &channel, + const QString &clientId = QString()) + Unsubscribes client from the broadcast channel of the provider service. + This is pure virtual function and needs to be implemented in the + inheritance. + + \param channnel + Channel name as QString + + \param clientId + Client id as QString + + \return + return true when successful, false otherwise. +*/ + +/*! + \fn QCloudMessagingProvider::remoteClients() + Requests remote clients from the provider services. + This is pure virtual function and needs to be implemented in the + inheritance. + + \return + return true if request successed, false otherwise +*/ + + +// Signals documentation +/*! + \fn QCloudMessagingProvider::clientTokenReceived(const QString &token) + This signal is triggered when connected gets the client + token from the service provider. + + \param token + Received token as a QString. + Token is unique identification value used for straight communication + and identification with the client. +*/ + +/*! + \fn QCloudMessagingProvider::messageReceived(const QString &providerId, + const QString &clientId, + const QByteArray &message) + This signal is triggered when a message is received from the network to client. + + \param providerId + Receiving Provider identification string + + \param clientId + Receiving clientId string + + \param message + Received message as QByteArray. Message is service specific. +*/ + +/*! + \fn QCloudMessagingProvider::remoteClientsReceived(const QString &clients) + This signal is triggered when the return value for requestRemoteClients + function is is received. + + \param response + Response data is based on the service and can be e.g. a list + of client tokens in QString format. +*/ + +/*! + \fn QCloudMessagingProvider::serviceStateUpdated(int state) + This signal is triggered when the service provider register + state has changed. + + \param state + State can be one of the enums from the QCloudMessagingProvider + +*/ + +/*! + \fn QCloudMessagingProvider::clientStateChanged( + const QString &clientId, + int state) + This signal is triggered when the client state has changed + + \param clientId + Client idenfitication string + + \param state + Client State can be either enum from QCloudMessagingClient::CloudMessagingClientState + or it can be client backend specific state. + +*/ + +// Public slots documentation + + +// Enums +/*! + \enum QCloudMessagingProvider::CloudMessagingProviderState + + This enum type describes types of QCloudMessagingProvider connection states. + + \value QtCloudMessagingProviderNotRegistered Messaging Provider is not registered. + \value QtCloudMessagingProviderRegistering Messaging Provider register started. + \value QtCloudMessagingProviderRegistered Messaging Provider registered. +*/ + +QT_END_NAMESPACE diff --git a/src/cloudmessaging/qcloudmessagingprovider.h b/src/cloudmessaging/qcloudmessagingprovider.h new file mode 100644 index 0000000..36130a7 --- /dev/null +++ b/src/cloudmessaging/qcloudmessagingprovider.h @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCLOUDMESSAGINGPROVIDER_H +#define QTCLOUDMESSAGINGPROVIDER_H + +#include <QObject> +#include <QVariantMap> +#include <QMap> +#include <QString> +#include <QScopedPointer> +#include <QtCloudMessaging/qtcloudmessagingglobal.h> +#include <QtCloudMessaging/qcloudmessagingclient.h> + +QT_BEGIN_NAMESPACE + +/*! + * \brief The QtCloudMessagingProvider class + */ +class QCloudMessagingProviderPrivate; + +class Q_CLOUDMESSAGING_EXPORT QCloudMessagingProvider : public QObject +{ + Q_OBJECT + +public: + + enum CloudMessagingProviderState { + QtCloudMessagingProviderNotRegistered, + QtCloudMessagingProviderRegistering, + QtCloudMessagingProviderRegistered + }; + Q_ENUM(CloudMessagingProviderState) + + explicit QCloudMessagingProvider(QObject *parent = nullptr); + ~QCloudMessagingProvider(); + + virtual bool registerProvider( + const QString &providerId, + const QVariantMap ¶meters = QVariantMap()); + + virtual void deregisterProvider(); + + virtual QString connectClient( + const QString &clientId, + const QVariantMap ¶meters = QVariantMap()) = 0; + + virtual void disconnectClient( + const QString &clientId, + const QVariantMap ¶meters = QVariantMap()); + + virtual bool sendMessage( + const QByteArray &msg, + const QString &clientId = QString(), + const QString &clientToken = QString(), + const QString &channel = QString()) = 0; + + virtual CloudMessagingProviderState setServiceState(QCloudMessagingProvider::CloudMessagingProviderState state); + + virtual QMap <QString, QCloudMessagingClient *> *clients(); + + QString clientToken(const QString &clientId); + + virtual bool remoteClients() = 0; + + QCloudMessagingClient *client(const QString &clientId); + + QString providerId(); + + void setProviderId(const QString &providerId); + + QCloudMessagingProvider::CloudMessagingProviderState getServiceState(); + + bool removeClient(const QString &clientId); + + virtual bool subscribeToChannel( + const QString &channel, + const QString &clientId = QString()) = 0; + + virtual bool unsubscribeFromChannel( + const QString &channel, + const QString &clientId = QString()) = 0; + + + bool flushMessageQueue(); + + QString connectClientToProvider( + const QString &clientId, + const QVariantMap ¶meters = QVariantMap(), + QCloudMessagingClient *serviceClient = nullptr); + +private Q_SLOTS: + void messageReceivedSlot(const QString &clientId, + const QByteArray &message); + +Q_SIGNALS: + void clientTokenReceived(const QString &token); + + void messageReceived(const QString &providerId, + const QString &clientId, + const QByteArray &message); + + void remoteClientsReceived(const QString &clients); + + void serviceStateUpdated(int state); + + void clientStateChanged(const QString &clientId, + int status); + + +private: + QScopedPointer<QCloudMessagingProviderPrivate> d; +}; + +QT_END_NAMESPACE + +#endif // QTCLOUDMESSAGINGPROVIDER_H diff --git a/src/cloudmessaging/qcloudmessagingprovider_p.h b/src/cloudmessaging/qcloudmessagingprovider_p.h new file mode 100644 index 0000000..5371363 --- /dev/null +++ b/src/cloudmessaging/qcloudmessagingprovider_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLOUDMESSAGINGCLIENT_P_H +#define QCLOUDMESSAGINGCLIENT_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QMap> +#include <QVariantMap> +#include <QtCloudMessaging/qtcloudmessagingglobal.h> + +QT_BEGIN_NAMESPACE + +class QCloudMessagingClient; +class QCloudMessagingProvider; + +class QCloudMessagingProviderPrivate +{ +public: + QCloudMessagingProviderPrivate() + : m_serviceState(0) + { + } + + ~QCloudMessagingProviderPrivate() = default; + + QString m_providerId; + int m_serviceState; + + QVariantMap m_provider_parameters; + QMap <QString, QCloudMessagingClient *> m_QtCloudMessagingClients; + +}; + +QT_END_NAMESPACE + +#endif // QCLOUDMESSAGINGCLIENT_P_H diff --git a/src/cloudmessaging/qcloudmessagingrestapi.cpp b/src/cloudmessaging/qcloudmessagingrestapi.cpp new file mode 100644 index 0000000..c59e538 --- /dev/null +++ b/src/cloudmessaging/qcloudmessagingrestapi.cpp @@ -0,0 +1,658 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcloudmessagingrestapi.h" +#include "qcloudmessagingrestapi_p.h" +#include <QUuid> +#include <QNetworkAccessManager> +#include <QNetworkRequest> +#include <QNetworkReply> +#include <QAuthenticator> +#include <QTimer> + +/*! + \class QCloudMessagingRestApi + \inmodule QtCloudMessaging + \since 5.11 + + \brief Cloud messaging services usually needs two way communication + from the server or the client. The QCloudMessagingRestApi class + provides the functions to send XML HTTP(s) requests to server or + other clients. + + The QCloudMessagingRestApi implements typical get, post, put and delete + functionalites. + + To use the class in own implementation, first inherit the + QCloudMessagingRestApi + class and then implement the virtual function to receive responses. + +*/ + +QT_BEGIN_NAMESPACE + +/*! + * \brief QCloudMessagingRestApi::QCloudMessagingRestApi + * QCloudMessagingRestApi constructor + * + * \param parent + * Parent as QObject + */ +QCloudMessagingRestApi::QCloudMessagingRestApi(QObject *parent) : + QObject(parent), + d(new QCloudMessagingRestApiPrivate) +{ + + d->m_online_state = d->m_network_info.isOnline(); + d->m_wait_for_last_request_response = false; + d->m_waiting_counter = 0; + + connect(&(d->m_network_info), &QNetworkConfigurationManager::onlineStateChanged, + this, &QCloudMessagingRestApi::onlineStateChanged); + + connect(&(d->m_manager), &QNetworkAccessManager::authenticationRequired, + this, &QCloudMessagingRestApi::provideAuthentication); + + connect(&(d->m_msgTimer), &QTimer::timeout, + this, &QCloudMessagingRestApi::networkMsgTimerTriggered); + +} + +/*! + * \brief QCloudMessagingRestApi::~QCloudMessagingRestApi + * Destructor + */ +QCloudMessagingRestApi::~QCloudMessagingRestApi() +{ +} + +/*! + * \brief QCloudMessagingRestApi::setServerTimers + * Sets rest server message retry and timeouts. + * + * \param messageTimer + * Timeout to wait before sending the next message. + * Same timeout is used for waiting response from the server. + * Useful when sending lot of message in fast sequency. + * Default is 800 milliseconds. + * + * \param waitForResponseCounter + * How long we wait for response to last send message + * Time is waitForResponseCounter x messageTimer milliseconds. + * Useful to tune for slower network conditions. + * Default is 3 times = 3 x 800 ms = 2400 ms + * + * \param messageRetryCount + * Describes how many times the message sending is retried if + * no response from the server. + */ +void QCloudMessagingRestApi::setServerTimers(int messageTimer, + int waitForResponseCounter, + int messageRetryCount) +{ + d->setServerTimers(messageTimer, waitForResponseCounter, messageRetryCount); +} + +/*! + * \brief QCloudMessagingRestApi::provideAuthentication + * Virtual function to provide authentication for the network connection. + * By default this function is omitted and service is connected without + * separate authentication. + * + * \param reply + * Sent QNetworkReply data + * \param authenticator + * Authenticator instance where to set username and password. + */ +void QCloudMessagingRestApi::provideAuthentication( + QNetworkReply *reply, + QAuthenticator *authenticator) +{ + Q_UNUSED(reply); + Q_UNUSED(authenticator); +} + +/*! + * \brief QCloudMessagingRestApi::xmlHttpPostRequest + * Private function to send Post specific message to server. + * Connects to virtualized xmlHttpRequestReply function. + * + * \param request + * QNetworkRequest instance + * + * \param data + * Data to be sent as QByteArray + + * \param req_id + * Requirement id to identify the received message. + * + * \param uuid + * Unique uuid for internal message array manipulation. + * + * \param info + * Additional info to provide via QNetworkReply instance + * + * \return + * Returns updated QNetworkReply instance after sending the post message. + */ +QNetworkReply * +QCloudMessagingRestApi::xmlHttpPostRequest( + QNetworkRequest request, + QByteArray data, + int req_id, + const QString &uuid, + const QString &info) +{ + + connect(&d->m_manager, &QNetworkAccessManager::finished, + this, &QCloudMessagingRestApi::xmlHttpRequestReply); + + QNetworkReply *reply = d->m_manager.post(request, data); + + reply->setProperty("req_id", req_id); + reply->setProperty("uuid", uuid); + reply->setProperty("info", info); + + return reply; +} + +/*! + * \brief QCloudMessagingRestApi::xmlHttpPutRequest + * Private function to send Put specific message to server. + * Connects to virtualized xmlHttpRequestReply function. + * + * \param request + * QNetworkRequest instance + * + * \param data + * Data to be sent as QByteArray + + * \param req_id + * Requirement id to identify the received message. + * + * \param uuid + * Unique uuid for internal message array manipulation. + * + * \param info + * Additional info to provide via QNetworkReply instance + * + * \return + * Returns updated QNetworkReply instance after sending the post message. + */ +QNetworkReply * +QCloudMessagingRestApi::xmlHttpPutRequest( + QNetworkRequest request, + QByteArray data, + int req_id, + const QString &uuid, + const QString &info) +{ + + connect(&d->m_manager, &QNetworkAccessManager::finished, + this, &QCloudMessagingRestApi::xmlHttpRequestReply); + + + QNetworkReply *reply = d->m_manager.put(request, data); + + reply->setProperty("req_id", req_id); + reply->setProperty("uuid", uuid); + reply->setProperty("info", info); + + return reply; +} + +/*! + * \brief QCloudMessagingRestApi::xmlHttpDeleteRequest + * Private function to send Delete specific message to server. + * Connects to virtualized xmlHttpRequestReply function. + * + * \param request + * QNetworkRequest instance + * + * \param data + * Data to be sent as QByteArray + + * \param req_id + * Requirement id to identify the received message. + * + * \param uuid + * Unique uuid for internal message array manipulation. + * + * \param info + * Additional info to provide via QNetworkReply instance + * + * \return + * Returns updated QNetworkReply instance after sending the post message. + */ +QNetworkReply * +QCloudMessagingRestApi::xmlHttpDeleteRequest( + QNetworkRequest request, + int req_id, + const QString &uuid, + const QString &info) +{ + + connect(&d->m_manager, &QNetworkAccessManager::finished, + this, &QCloudMessagingRestApi::xmlHttpRequestReply); + + + QNetworkReply *reply = d->m_manager.deleteResource(request); + + reply->setProperty("req_id", req_id); + reply->setProperty("uuid", uuid); + reply->setProperty("info", info); + + return reply; +} + +/*! + * \brief QCloudMessagingRestApi::xmlHttpGetRequest + * Private function to send Get specific message to server. + * Connects to virtualized xmlHttpRequestReply function. + * + * \param request + * QNetworkRequest instance + * + * \param data + * Data to be sent as QByteArray + + * \param req_id + * Requirement id to identify the received message. + * + * \param uuid + * Unique uuid for internal message array manipulation. + * + * \param info + * Additional info to provide via QNetworkReply instance + * + * \return + * Returns updated QNetworkReply instance after sending the post message. + */ +QNetworkReply *QCloudMessagingRestApi::xmlHttpGetRequest( + QNetworkRequest request, + int req_id, + const QString &uuid, + const QString &info) +{ + + connect(&d->m_manager, &QNetworkAccessManager::finished, + this, &QCloudMessagingRestApi::xmlHttpRequestReply); + + + QNetworkReply *reply = d->m_manager.get(request); + + reply->setProperty("req_id", req_id); + reply->setProperty("uuid", uuid); + reply->setProperty("info", info); + + return reply; +} + +/*! + * \brief QCloudMessagingRestApi::sendNetworkMessage + * Sends message with info from the QCloudMessagingNetworkMessage class parameter. + * + * \param msg + * QCloudMessagingNetworkMessage class as parameter + * + * \param immediate + * If true, defines that message is sent immediately and no message timers are involved + * if false, message is set to message queue and message will be sent after message timer + * timeouts. + */ +void QCloudMessagingRestApi::sendNetworkMessage( + const QCloudMessagingNetworkMessage &msg, + int immediate) +{ + sendMessage((QCloudMessagingRestApi::MessageType)msg.type, + msg.req_id, + msg.request, + msg.data, + immediate, + QString()); +} + +/*! + * \brief QCloudMessagingRestApi::sendMessage + * Sends type specific network message to server + * + * \param type + * Type as QCloudMessagingRestApi::MessageType + * + * \param req_id + * Requirement id to identify the received message. + * + * \param request + * QNetworkRequest instance + * + * \param data + * Data to be sent as QByteArray + * + * \param immediate + * If true, defines that message is sent immediately and no message timers are involved + * if false, message is set to message queue and message will be sent after message timer + * timeouts. + * + * \param info + * Additional info to provide via QNetworkReply instance + * + * \return + * Return true if message was sent immediately. False if it went to the queue. + */ +bool QCloudMessagingRestApi::sendMessage(QCloudMessagingRestApi::MessageType type, + int req_id, + QNetworkRequest request, + QByteArray data, + int immediate, + const QString &info) +{ + QCloudMessagingNetworkMessage msg; + bool sent = false; + + // Remember the message if not online + if (!immediate || !d->m_online_state) { + QUuid quid = QUuid::createUuid();; + + QString pure_quid = quid.toString(); + pure_quid = pure_quid.mid(1, pure_quid.length() - 2); + + msg.req_id = req_id; + msg.type = type; + msg.uuid = pure_quid; + msg.request = request; + msg.data = data; + msg.retry_count = 0; + msg.info = info; + + d->m_network_requests.append(msg); + + if (!d->m_msgTimer.isActive()) d->m_msgTimer.start(d->m_server_message_timer); + } else { + if (type == POST_MSG) { + xmlHttpPostRequest(request, data, req_id, msg.uuid, info); + } + + if (type == GET_MSG) { + xmlHttpGetRequest(request, req_id, msg.uuid, info); + } + if (type == PUT_MSG) { + xmlHttpPutRequest(request, data, req_id, msg.uuid, info); + } + if (type == DELETE_MSG) { + xmlHttpDeleteRequest(request, req_id, msg.uuid, info); + } + sent = true; + } + return sent; +} + +/*! + * \brief QCloudMessagingRestApi::clearMessage + * Clears the specific messages from the message queue + * Should be used in the implementatio of xmlHttpRequestReply + * + * \param msg_uuid + * Unique uuid of the message + */ +void QCloudMessagingRestApi::clearMessage(const QString &msg_uuid) +{ + for (int i = 0; i < d->m_network_requests.length(); i++) { + if (d->m_network_requests[i].uuid == msg_uuid) { + d->m_network_requests.removeAt(i); + return; + } + } +} + + +/*! + * \brief QCloudMessagingRestApi::clearMessageBuffer + * Clears the message queue. + */ +void QCloudMessagingRestApi::clearMessageBuffer() +{ + d->m_network_requests.clear(); +} + +/*! + * \brief QCloudMessagingRestApi::networkMsgTimerTriggered + * Private slot for handling message timeouts and resending of the + * messages. + */ +void QCloudMessagingRestApi::networkMsgTimerTriggered() +{ + // Do not send messages if we are not online or we are waiting + // for message to arrive + if (!d->m_online_state) { + d->m_msgTimer.start(d->m_server_message_timer); + return; + } + + if (d->m_wait_for_last_request_response) { + d->m_waiting_counter++; + + if (d->m_waiting_counter > d->m_server_wait_for_response_counter) { + d->m_wait_for_last_request_response = false; + d->m_waiting_counter = 0; + } + d->m_msgTimer.start(d->m_server_message_timer); + return; + } + + d->m_waiting_counter = 0; + + // Send latest message. + if (d->m_network_requests.length() > 0) { + + if (d->m_network_requests[0].type == POST_MSG) { + + xmlHttpPostRequest(d->m_network_requests[0].request, + d->m_network_requests[0].data, + d->m_network_requests[0].req_id, + d->m_network_requests[0].uuid, + d->m_network_requests[0].info); + + d->m_network_requests[0].retry_count++; + } + + if (d->m_network_requests[0].type == GET_MSG && + d->m_network_requests[0].retry_count < d->m_server_message_retry_count) { + + xmlHttpGetRequest(d->m_network_requests[0].request, + d->m_network_requests[0].req_id, + d->m_network_requests[0].uuid, + d->m_network_requests[0].info); + + d->m_network_requests[0].retry_count++; + } + + if (d->m_network_requests[0].type == PUT_MSG && + d->m_network_requests[0].retry_count < d->m_server_message_retry_count) { + + xmlHttpPutRequest(d->m_network_requests[0].request, + d->m_network_requests[0].data, + d->m_network_requests[0].req_id, + d->m_network_requests[0].uuid, + d->m_network_requests[0].info); + + d->m_network_requests[0].retry_count++; + } + + if (d->m_network_requests[0].type == DELETE_MSG && + d->m_network_requests[0].retry_count < d->m_server_message_retry_count) { + + xmlHttpDeleteRequest(d->m_network_requests[0].request, + d->m_network_requests[0].req_id, + d->m_network_requests[0].uuid, + d->m_network_requests[0].info); + + d->m_network_requests[0].retry_count++; + } + + if (d->m_network_requests[0].retry_count < d->m_server_message_retry_count) { + d->m_network_requests.move(0, d->m_network_requests.length() - 1); + } else { + d->m_network_requests.removeAt(0); + } + + if (d->m_network_requests.length() > 0) + d->m_msgTimer.start(d->m_server_message_timer); + } +} + +/*! + * \brief QCloudMessagingRestApi::onlineStateChanged + * Private slot for saving the online state based on the network class + * info + * + * \param online + * True if online, false if offline + */ +void QCloudMessagingRestApi::onlineStateChanged(bool online) +{ + d->m_online_state = online; +} + +/*! + * \brief QCloudMessagingRestApi::getNetworkRequestCount + * Returns the count of network messages in the queue waiting + * to be sent. + * + * \return + * Returns amount of network messages in queue. + */ +int QCloudMessagingRestApi::getNetworkRequestCount() +{ + return d->m_network_requests.count(); +} + +/*! + * \brief QCloudMessagingRestApi::getOnlineState + * Get the current online state info from the class. + * + * \return + * Returns true if online. False if offline. + */ +bool QCloudMessagingRestApi::getOnlineState() +{ + return d->m_online_state; +} + +/*! + * \brief QCloudMessagingRestApi::getNetworkManager + * Gets the QNetworkAccessManager for the current connection. + * Used in xmlHttpRequestReply implementation. + * + * \return + * Return the used QNetworkAccessManager instance. + */ +QNetworkAccessManager *QCloudMessagingRestApi::getNetworkManager() +{ + return &(d->m_manager); +} + +// Signals documentation +/*! + \fn QCloudMessagingRestApi::xmlHttpRequestError(const QString &errorString) + This signal is emitted when there is an error in the network transport. + + \param errorString + Error message as QString +*/ + +// Public slots documentation +/*! + \fn virtual void QCloudMessagingRestApi:: xmlHttpRequestReply(QNetworkReply *reply) + + This slot is executed when \c QNetworkReply is received for the client request. + This is virtual function which needs to be implemented the by inheriting class. + + Example implementation: + \code + void QCloudMessagingEmbeddedKaltiotRest::xmlHttpRequestReply(QNetworkReply *reply) + { + getNetworkManager()->disconnect(SIGNAL(finished(QNetworkReply *))); + + QString m_msg_uuid = reply->property("uuid").toString(); + int req_id = reply->property("req_id").toInt(); + + if (reply->error()) { + Q_EMIT xmlHttpRequestError(reply->errorString()); + } + + // Ok message, lets proceed and read all + QByteArray data(reply->readAll()); + + // Make decisions about req_id + switch (req_id) { + case REQ_GET_ALL_DEVICES: { + emit remoteClientsReceived(QString::fromUtf8(data)); + } + } + + reply->deleteLater(); + + clearMessage(m_msg_uuid); + + } + \endcode + \param reply + provides QNetworkReply for reading data from the network response. + + +*/ + +/*! + \fn QCloudMessagingRestApi::provideAuthentication(QNetworkReply *reply, QAuthenticator *authenticator) + This slot is executed when network request requires authentication. + This is virtual function which needs to be implemented by inheriting class if + created service is know to request specific authentications. Otherwise + provideAuthentication request is omitted. + + \param reply + provides QNetworkReply for reading data from the network response. + + \param authentication + QAuthenticator pointer to provide username and password back. +*/ + +// Enums +/*! + \enum QCloudMessagingRestApi::MessageType + + This enum type describes types of QCloudMessagingRestApi xmlHttpRequest + messaging types. + + \value NO_TYPE No type. + \value POST_MSG Post message type for uploading data to server. + \value GET_MSG Get message type for requesting data from the server. + \value PUT_MSG Put message type for updating data in the server. + \value DELETE_MSG Delete message type for deleting data from the server. +*/ + +QT_END_NAMESPACE diff --git a/src/cloudmessaging/qcloudmessagingrestapi.h b/src/cloudmessaging/qcloudmessagingrestapi.h new file mode 100644 index 0000000..c609289 --- /dev/null +++ b/src/cloudmessaging/qcloudmessagingrestapi.h @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCLOUDMESSAGINGRESTAPI_H +#define QTCLOUDMESSAGINGRESTAPI_H + +#include <QtCloudMessaging/qtcloudmessagingglobal.h> +#include <QtCloudMessaging/qcloudmessagingprovider.h> + +#include <QObject> +#include <QNetworkRequest> +#include <QScopedPointer> + +QT_BEGIN_NAMESPACE + +class QNetworkAccessManager; +class QAuthenticator; +class QNetworkReply; + + +class QCloudMessagingNetworkMessage +{ +public: + int type; + int req_id; + QString uuid; + QNetworkRequest request; + QByteArray data; + QString related_uuid; + QString info; + int retry_count; + +}; + +class QCloudMessagingRestApiPrivate; + +class Q_CLOUDMESSAGING_EXPORT QCloudMessagingRestApi : public QObject +{ + Q_OBJECT + +public: + + enum MessageType{ + NO_TYPE = 0, + POST_MSG, + GET_MSG, + PUT_MSG, + DELETE_MSG + }; + Q_ENUM(MessageType) + + explicit QCloudMessagingRestApi(QObject *parent = nullptr); + + ~QCloudMessagingRestApi(); + + + bool sendMessage(MessageType type, int req_id, QNetworkRequest request, + QByteArray data, int immediate, + const QString &related_uuid); + + void sendNetworkMessage(const QCloudMessagingNetworkMessage &msg, + int immediate); + + void clearMessageBuffer(); + + int getNetworkRequestCount(); + + bool getOnlineState(); + + QNetworkAccessManager *getNetworkManager(); + + void setServerTimers(int messageTimer, + int messageRetryCount, + int messageNoResponseTimer); + + void clearMessage(const QString &msg_uuid); + + QNetworkReply *xmlHttpPostRequest(QNetworkRequest request, + QByteArray data, + int req_id, + const QString &uuid, + const QString &info); + + QNetworkReply *xmlHttpGetRequest(QNetworkRequest request, + int req_id, + const QString &uuid, + const QString &info); + + QNetworkReply *xmlHttpPutRequest(QNetworkRequest request, + QByteArray data, + int req_id, + const QString &uuid, + const QString &info); + + QNetworkReply *xmlHttpDeleteRequest(QNetworkRequest request, + int req_id, + const QString &uuid, + const QString &info); +Q_SIGNALS: + void xmlHttpRequestError(const QString &errorString); + +public Q_SLOTS: + virtual void xmlHttpRequestReply(QNetworkReply *reply) = 0; + virtual void provideAuthentication(QNetworkReply *reply, QAuthenticator *authenticator); + +private Q_SLOTS: + void networkMsgTimerTriggered(); + void onlineStateChanged(bool online); + +private: + void append_network_request(int req_id, const QString ¶m, QVariant data); + + QScopedPointer<QCloudMessagingRestApiPrivate> d; + +}; + +QT_END_NAMESPACE + +#endif // QTCLOUDMESSAGINGRESTAPI_H diff --git a/src/cloudmessaging/qcloudmessagingrestapi_p.h b/src/cloudmessaging/qcloudmessagingrestapi_p.h new file mode 100644 index 0000000..71e0547 --- /dev/null +++ b/src/cloudmessaging/qcloudmessagingrestapi_p.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCLOUDMESSAGINGRESTAPI_P_H +#define QTCLOUDMESSAGINGRESTAPI_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +#include <QtCloudMessaging/qtcloudmessagingglobal.h> +#include <QList> +#include <QNetworkReply> +#include <QTimer> +#include <QNetworkAccessManager> +#include <QNetworkConfigurationManager> + +QT_BEGIN_NAMESPACE + +class QCloudMessagingNetworkMessage; + +class QCloudMessagingRestApiPrivate +{ +public: + QCloudMessagingRestApiPrivate() + { + m_online_state = false; + m_server_message_timer = 800; + m_server_wait_for_response_counter = 10; + m_server_message_retry_count = 1; + } + + ~QCloudMessagingRestApiPrivate() = default; + + void setServerTimers(int messageTimer, int waitForResponseCounter, int messageRetryCount) + { + m_server_message_timer = messageTimer; + m_server_wait_for_response_counter = waitForResponseCounter; + m_server_message_retry_count = messageRetryCount; + } + + QNetworkAccessManager m_manager; + bool m_wait_for_last_request_response; + QTimer m_msgTimer; + bool m_online_state; + QList <QCloudMessagingNetworkMessage> m_network_requests; + QNetworkConfigurationManager m_network_info; + int m_waiting_counter; + int m_server_message_timer; + int m_server_wait_for_response_counter; + int m_server_message_retry_count; + +}; + +QT_END_NAMESPACE + +#endif // QTCLOUDMESSAGINGRESTAPI_P_H diff --git a/src/cloudmessaging/qtcloudmessagingglobal.h b/src/cloudmessaging/qtcloudmessagingglobal.h new file mode 100644 index 0000000..2cc131e --- /dev/null +++ b/src/cloudmessaging/qtcloudmessagingglobal.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCLOUDMESSAGINGGLOBAL_H +#define QTCLOUDMESSAGINGGLOBAL_H +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +#ifndef QT_STATIC +# if defined(QT_BUILD_CLOUDMESSAGING_LIB) +# define Q_CLOUDMESSAGING_EXPORT Q_DECL_EXPORT +# else +# define Q_CLOUDMESSAGING_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_CLOUDMESSAGING_EXPORT +#endif + +QT_END_NAMESPACE + +#endif // QTCLOUDMESSAGINGGLOBAL_H diff --git a/src/cloudmessagingembeddedkaltiot/android/ks_gw_client_android.h b/src/cloudmessagingembeddedkaltiot/android/ks_gw_client_android.h new file mode 100644 index 0000000..b6184b8 --- /dev/null +++ b/src/cloudmessagingembeddedkaltiot/android/ks_gw_client_android.h @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (c) by Kaltiot Oy 2017 +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef __STATIC_LIBRARY_KS_GW_CLIENT_H__ +#define __STATIC_LIBRARY_KS_GW_CLIENT_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> +#include <stdbool.h> + +typedef enum { + KS_STATE_OFFLINE, + KS_STATE_DISCONNECTING, + KS_STATE_CONNECTING, + KS_STATE_ONLINE +} KaltiotSmartState; + +typedef enum { + KS_ERROR_NO_ERROR = 0, + KS_ERROR_CONNECT_ERROR, + KS_ERROR_GATEWAY_DISCONNECT, + KS_ERROR_UNKNOWN, + KS_ERROR_CLIENT_DISCONNECT +} KaltiotSmartError; + +typedef enum { + KS_GW_CLIENT_PAYLOAD_BINARY = 1, + KS_GW_CLIENT_PAYLOAD_INT, + KS_GW_CLIENT_PAYLOAD_STRING, + KS_GW_CLIENT_PAYLOAD_PING, + KS_GW_CLIENT_PAYLOAD_PONG +} payload_type_t; + +typedef enum { + NETWORK_STATE_DISABLED, + NETWORK_STATE_MOBILE_2G, + NETWORK_STATE_MOBILE_3G, + NETWORK_STATE_MOBILE_4G, + NETWORK_STATE_MOBILE_5G, + NETWORK_STATE_WIFI, + NETWORK_STATE_COUNT +} network_state_e; + +typedef struct { + void* userdata; + bool connected; + int32_t socket_fd; + void* old_info; +} ks_gw_client_instance_t; + + +/** + * Callback function that is called when a notification is received. You + * should implement this. + * + * If payload_type is KS_CLIENT_PAYLOAD_STRING, KS_CLIENT_PAYLOAD_PING or + * KS_CLIENT_PAYLOAD_PONG, payload and length will include the null + * terminator of the string. + * + * @param address Null-terminated string. + * @param payload Byte data. + * @param payload_length Length of the payload. + * @param payload_type Type of the payload. + * @param msg_id Message id + * @param msg_id_length Message id length + + */ +void ks_gw_client_notification_cb(const char *address, const char *payload, + const uint16_t payload_length, + const payload_type_t payload_type, + const char *msg_id, + const uint16_t msg_id_length); + +/** + * Callback function that is called when a rid is received. You should + * implement this. + * + * @param address Null-terminated string. + * @param rid Null-terminated string. + Unique resource identifier for every iot application + registered to the service. Using this identifier you are + able to send notifications to the application. + * @param secret Null-terminated string. + */ +void ks_gw_client_rid_cb(const char *address, const char *rid, + const char *secret); + +/** + * Callback function that is called when the state of the daemon changes. You + * should implement this. + * + * @param state Status code that tells the new state. + * @param error Possible error code associated with the state. + */ +void ks_gw_client_state_changed_cb(KaltiotSmartState state, KaltiotSmartError error); + + +/** + * Initialize the client instance. Must be the first function to call for new client. + */ +void ks_gw_client_init(ks_gw_client_instance_t *inst); + +/** + * Connects to the daemon. Call this before registering. Returns true if the + * connection has been successfully established. + * + * @param path The path or address to connect to. It is treated as a unix + * domain socket path unless it has a colon in it, in which case + * the IPC will use local TCP on ip:port. You can also leave it + * NULL, then the default path (/tmp/ks_gw_socket) will be + * used. + */ +extern bool ks_gw_client_connect(ks_gw_client_instance_t *inst, const char *path); + +/** + * Disconnects from the daemon. + */ +extern void ks_gw_client_disconnect(ks_gw_client_instance_t *inst); + +/** + * Registers with the daemon. App will start receiving notifications and other + * events. + * + * NOTE: If you need to update the channels, you have to first unregister + * and then register again, with the different channels. + * + * @param address Alphanumeric, null-terminated string. + * @param version Alphanumeric, null-terminated string. + * @param customer_id Alphanumeric, null-terminated string. + Identifier given by customer to the IoT application + registering to Kaltiot Smart Iot. Use this field to identify your + iot application on gateway. It has to be unique for a + given gateway. For example "sensor1". + * @param channels Array of alphanumeric, null-terminated strings that + * represent the channels such as "temperature" or + * "motion". + * @param num_channels The number of channels in the array. + */ +extern void ks_gw_client_register_iot(ks_gw_client_instance_t *inst, + const char *address, + const char *version, + const char *customer_id, + const char **channels, + uint16_t num_channels); + +/** + * Unregisters from the daemon. + * + * @param address Alphanumeric, null-terminated string. + * @param version Alphanumeric, null-terminated string. + * @param customer_id Alphanumeric, null-terminated string. + */ +extern void ks_gw_client_unregister_iot(ks_gw_client_instance_t *inst, + const char *address, + const char *version, + const char *customer_id); + +/** + * Publishes a message to the server. + * + * If payload_type is KS_CLIENT_PAYLOAD_STRING, KS_CLIENT_PAYLOAD_PING or + * KS_CLIENT_PAYLOAD_PONG, payload and length should include the null + * terminator of the string. + * + * @param payload Byte data. + * @param payload_len Length of the payload. + * @param payload_type Type of the payload. + * @param tag Tag of the payload. maximum size could be MAX_TAG_LENGTH + * @return bool true if the parameters are valid else false + */ +extern bool ks_gw_client_publish_message(ks_gw_client_instance_t *inst, + const uint8_t *payload, + const uint16_t payload_len, + const payload_type_t payload_type, + const char* tag); + +/** + * Should be called periodically. It checks whether there is any data waiting + * to be read in the buffer, and based on said data calls the above callbacks. + */ +extern void ks_gw_client_task(ks_gw_client_instance_t *inst); + +/** + * Forces state_changed_cb to be called with the current state. + */ +extern void ks_gw_client_request_state(ks_gw_client_instance_t *inst); + +/** + * Forces rid_cb to be called with the current rid info. + */ +extern void ks_gw_client_request_rid(ks_gw_client_instance_t *inst); + +typedef void (*ks_app_id_callback) (const char *app_id, void *arg); + +/** + * Requests the application id from the daemon. The callback is called with + * the application id and an optional argument that the user can specify. + * + * @param callback Callback function. + * @param arg Optional argument passed to the callback. + */ +extern void ks_gw_client_request_app_id(ks_gw_client_instance_t *inst, + ks_app_id_callback callback, + void *arg); + +/** + * Enables or disables the entire engine. Equivalent to closing the daemon. + * + * @param enabled + */ +extern void ks_gw_client_set_engine_enabled(ks_gw_client_instance_t *inst, bool enabled); + +/** + * Sets the network status. MCC and MNC can be included with a mobile network + * state. + * + * @param state + * @param mcc Can be an empty null-terminated string, not NULL. + * @param mnc Can be an empty null-terminated string, not NULL. + */ +extern void ks_gw_client_set_network_available(ks_gw_client_instance_t *inst, + network_state_e state, + const char *mcc, const char *mnc); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/cloudmessagingembeddedkaltiot/cloudmessagingembeddedkaltiot.pro b/src/cloudmessagingembeddedkaltiot/cloudmessagingembeddedkaltiot.pro new file mode 100644 index 0000000..1190234 --- /dev/null +++ b/src/cloudmessagingembeddedkaltiot/cloudmessagingembeddedkaltiot.pro @@ -0,0 +1,48 @@ +TARGET = QtCloudMessagingEmbeddedKaltiot +QT = core cloudmessaging + +# Check for KALTIOT_SDK environment +ENV_KALTIOT_SDK = $$(KALTIOT_SDK) + +# Or define KALTIOT_SDK path here +KALTIOT_SDK = + +isEmpty(ENV_KALTIOT_SDK) { + isEmpty(KALTIOT_SDK) { + message("KALTIOT_SDK" environment variable or define in radardemo.pro file not detected!) + } +} + +INCLUDEPATH += $$(KALTIOT_SDK) +INCLUDEPATH += $$(KALTIOT_SDK)/src + +HEADERS += \ + qcloudmessagingembeddedkaltiotclient.h \ + qcloudmessagingembeddedkaltiotprovider.h \ + qcloudmessagingembeddedkaltiotclient_p.h \ + qcloudmessagingembeddedkaltiotprovider_p.h \ + qcloudmessagingembeddedkaltiotrest.h + +SOURCES += \ + qcloudmessagingembeddedkaltiotclient.cpp \ + qcloudmessagingembeddedkaltiotprovider.cpp \ + qcloudmessagingembeddedkaltiotrest.cpp + +android { + DEFINES += ANDROID_OS + QT += androidextras + HEADERS += \ + $$PWD/android/ks_gw_client_android.h +} else { + + DEFINES += EMBEDDED_AND_DESKTOP_OS + HEADERS += \ + $$(KALTIOT_SDK)/src/ks_gw_client.h + + LIBS += $$(KALTIOT_SDK)/libks_gw_client.a +} + +load(qt_module) + +DISTFILES += \ + README.md diff --git a/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotclient.cpp b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotclient.cpp new file mode 100644 index 0000000..c1325dd --- /dev/null +++ b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotclient.cpp @@ -0,0 +1,342 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcloudmessagingembeddedkaltiotclient.h" +#include <qcloudmessagingembeddedkaltiotclient_p.h> + +#include <QStringList> + +#ifdef ANDROID_OS +#include <QtAndroid> +#include "jni.h" +#endif + +QT_BEGIN_NAMESPACE + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::QCloudMessagingEmbeddedKaltiotClient + * Kaltiot client constructor + */ +QCloudMessagingEmbeddedKaltiotClient::QCloudMessagingEmbeddedKaltiotClient(QObject *parent) : + QCloudMessagingClient(parent), + d(new QCloudMessagingEmbeddedKaltiotClientPrivate) +{ +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::~QCloudMessagingEmbeddedKaltiotClient + * Desctructor + */ +QCloudMessagingEmbeddedKaltiotClient::~QCloudMessagingEmbeddedKaltiotClient() +{ + // if thread is running, ask for exit it first and then terminate thread + if (d->m_running && d->m_clientThread.isRunning()) { + d->m_running = false; + d->m_clientThread.quit(); + d->m_clientThread.terminate(); + } +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::connectClient + * \param clientId + * \param parameters + * \return + */ +QString QCloudMessagingEmbeddedKaltiotClient::connectClient(const QString &clientId, + const QVariantMap ¶meters) +{ + // Call parent function to setup service ids and states. + QCloudMessagingClient::connectClient(clientId, parameters); + + QStringList channels; + QVariantMap params = parameters; + d->m_address = params.value(QStringLiteral("address")).toString(); + d->m_version = params.value(QStringLiteral("version")).toString(); + d->m_customer_id = params.value(QStringLiteral("customer_id")).toString(); + + channels = params.value(QStringLiteral("channels")).toStringList(); + + for (int i = 0; i < channels.count(); i++) { + bool new_channel = true; + for (int j = 0; i < d->m_channels.count(); j++) { + if (channels[i] == d->m_channels[j]) + new_channel = false; + } + if (new_channel) { + d->m_channels.append(channels[i]); + } + } + + setClientToken(clientId); + make_kaltiot_client_registration(); + runBackgroundThread(); + return d->m_address; +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::runBackgroundThread + */ +void QCloudMessagingEmbeddedKaltiotClient::runBackgroundThread() +{ + this->moveToThread(&d->m_clientThread); + d->m_clientThread.start(); + + // Run service task in the thread. + connect(&(d->m_threadTimer), &QTimer::timeout, [ = ] { + + if (!d->m_running) d->m_running = true; +#ifdef EMBEDDED_AND_DESKTOP_OS + ks_gw_client_task(&d->m_kaltiot_client_instance); +#endif + d->m_threadTimer.start(); + }); + + d->m_threadTimer.setInterval(1); + d->m_threadTimer.start(); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::make_kaltiot_client_registration + */ +void QCloudMessagingEmbeddedKaltiotClient::make_kaltiot_client_registration() +{ +#ifdef EMBEDDED_AND_DESKTOP_OS + + char const *channels[d->m_channels.count()]; + QList<QByteArray> constChannels; + + for (int i = 0; i < d->m_channels.count(); i++) { + constChannels.append(d->m_channels[i].toLatin1()); + channels[i] = constChannels[constChannels.count()-1].constData(); + } + + uint16_t num_channels = d->m_channels.count(); + + ks_gw_client_init(&d->m_kaltiot_client_instance); + + if (!ks_gw_client_connect(&d->m_kaltiot_client_instance, NULL)) { + // Failed to connect!; + return; + } + + if (d->m_rid.isEmpty()) { + d->m_rid = d->m_client_settings.value("clients/" + d->m_address + "/rid").toString(); + } + + if (!d->m_rid.isEmpty()) + setClientToken(d->m_rid); + + ks_gw_client_set_engine_enabled(&d->m_kaltiot_client_instance, true); + + ks_gw_client_set_network_available(&d->m_kaltiot_client_instance, + NETWORK_STATE_MOBILE_2G, "123","45"); + + ks_gw_client_register_iot(&d->m_kaltiot_client_instance, + d->m_address.toLatin1().constData(), + d->m_version.toLatin1().constData(), + d->m_customer_id.toLatin1().constData(), + channels, num_channels); + + ks_gw_client_request_rid(&d->m_kaltiot_client_instance); + + constChannels.clear(); + +#endif + +#ifdef ANDROID_OS + + QAndroidJniObject j_rid = QtAndroid::androidActivity().callObjectMethod<jstring>("get_rid"); + + d->m_rid = j_rid.toString(); + if (d->m_rid.isEmpty()) { + d->m_rid = d->m_client_settings.value("clients/" + d->m_address + "/rid").toString(); + + } + if (!d->m_rid.isEmpty()) + setClientToken(d->m_rid); + +#endif +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::sendMessage + * \param msg + * \param send_to_device + * \param send_to_channel + * \return + */ +bool QCloudMessagingEmbeddedKaltiotClient::sendMessage(const QByteArray &msg, + const QString &clientToken, + const QString &channel) +{ + // In Kaltiot client send message goes via client daemon and channel or + // clientToken attributes are not used. + Q_UNUSED(channel); + Q_UNUSED(clientToken); + + +#ifdef EMBEDDED_AND_DESKTOP_OS + // TAG NOT USED ATM. + ks_gw_client_publish_message(&d->m_kaltiot_client_instance, + (const uint8_t *)msg.constData(), + msg.size(), + KS_GW_CLIENT_PAYLOAD_STRING, + nullptr); +#endif + + return true; +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::disconnectClient + * \return + */ +void QCloudMessagingEmbeddedKaltiotClient::disconnectClient() +{ + QCloudMessagingClient::disconnectClient(); + + d->m_running = false; +#ifdef EMBEDDED_AND_DESKTOP_OS + ks_gw_client_unregister_iot(&d->m_kaltiot_client_instance, d->m_address.toLatin1(), + d->m_version.toLatin1(), clientToken().toLatin1()); + ks_gw_client_disconnect(&d->m_kaltiot_client_instance); + ks_gw_client_set_engine_enabled(&d->m_kaltiot_client_instance, false); +#endif +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::cloudMessageReceived + * \param client + * \param message + */ +void QCloudMessagingEmbeddedKaltiotClient::cloudMessageReceived(const QString &client, + const QByteArray &message) +{ + emit messageReceived(client, message); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::setClientToken + * \param token + */ +void QCloudMessagingEmbeddedKaltiotClient::setClientToken(const QString &token) +{ + d->m_rid = token; + if (!d->m_rid.isEmpty()) + d->m_client_settings.setValue("clients/" + d->m_address + "/rid", d->m_rid); + + emit clientTokenReceived(d->m_rid); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::clientToken + * \return + */ +QString QCloudMessagingEmbeddedKaltiotClient::clientToken() +{ + return d->m_rid; +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::getKaltiotEngineInstance + * \return + */ +ks_gw_client_instance_t *QCloudMessagingEmbeddedKaltiotClient::getKaltiotEngineInstance() +{ + return &d->m_kaltiot_client_instance; +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::subscribeToChannel + * * Unsubscribes client from the channel + * + * \param channel + * * Channel name QString + * + * \return + * false if channel not found, true if found and updated + */ +bool QCloudMessagingEmbeddedKaltiotClient::subscribeToChannel(const QString &channel) +{ + + for (int i = 0; i < d->m_channels.count(); i++) { + if (channel == d->m_channels[i]) + return false; // Already subscribed + } + + // Not found, lets add new channel and restart client. + d->m_channels.append(channel); + + disconnectClient(); + connectClient(clientToken(), clientParameters()); + + return true; +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::unsubscribeFromChannel + * Unsubscribes client from the channel + * + * \param channel + * Channel name QString + * + * \return + * false if channel not found, true if found and updated + */ +bool QCloudMessagingEmbeddedKaltiotClient::unsubscribeFromChannel(const QString &channel) +{ + + for (int i = 0; i < d->m_channels.count(); i++) { + if (channel == d->m_channels[i]) { + d->m_channels.removeAt(i); + + disconnectClient(); + connectClient(clientToken(), clientParameters()); + + return true; + } + } + return false; // Not found + + +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotClient::flushMessageQueue + * \return + */ +bool QCloudMessagingEmbeddedKaltiotClient::flushMessageQueue() +{ + return true; +} + +// Provide link to main - which will be in the app using this service. +extern int main(int argc, char *argv[]); + +QT_END_NAMESPACE diff --git a/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotclient.h b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotclient.h new file mode 100644 index 0000000..e592efa --- /dev/null +++ b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotclient.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCloudMessagingEmbeddedKaltiotClient_H +#define QCloudMessagingEmbeddedKaltiotClient_H + +#include <QtCloudMessaging/QtCloudMessaging> +#include <QtCloudMessaging/qtcloudmessagingglobal.h> + +#include <QObject> +#include <QVariantMap> +#include <QString> +#include <QScopedPointer> + +#ifndef ANDROID_OS +#include "ks_gw_client.h" +#else +#include "ks_gw_client_android.h" +#endif + +QT_BEGIN_NAMESPACE + +class QCloudMessagingEmbeddedKaltiotClientPrivate; + +class Q_CLOUDMESSAGING_EXPORT QCloudMessagingEmbeddedKaltiotClient : public QCloudMessagingClient +{ + Q_OBJECT +public: + + explicit QCloudMessagingEmbeddedKaltiotClient(QObject *parent = nullptr); + ~QCloudMessagingEmbeddedKaltiotClient(); + + // Qt Cloud messaging client virtual functions + virtual QString connectClient(const QString &clientId, + const QVariantMap ¶meters = QVariantMap()) override; + + virtual void disconnectClient() override; + + virtual void cloudMessageReceived(const QString &client, const QByteArray &message) override; + + virtual QString clientToken() override; + + virtual void setClientToken(const QString &token) override; + + virtual bool sendMessage(const QByteArray &msg, + const QString &clientToken = QString(), + const QString &channel = QString()) override; + + + virtual bool flushMessageQueue() override; + + virtual bool subscribeToChannel(const QString &channel) override; + + virtual bool unsubscribeFromChannel(const QString &channel) override; + + void kaltiotMessageReceived(const QString &client, const QString &message); + + ks_gw_client_instance_t *getKaltiotEngineInstance(); + +private: + void make_kaltiot_client_registration(); + void runBackgroundThread(); + + QScopedPointer<QCloudMessagingEmbeddedKaltiotClientPrivate> d; + +}; + +QT_END_NAMESPACE + +#endif // QCloudMessagingEmbeddedKaltiotClient_H diff --git a/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotclient_p.h b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotclient_p.h new file mode 100644 index 0000000..f92b52a --- /dev/null +++ b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotclient_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLOUDMESSAGINGCLIENT_P_H +#define QCLOUDMESSAGINGCLIENT_P_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCloudMessaging/qtcloudmessagingglobal.h> +#include <QStringList> +#include <QSettings> +#include <QThread> +#include <QTimer> + +#ifndef ANDROID_OS +#include "ks_gw_client.h" +#else +#include "ks_gw_client_android.h" +#endif + +QT_BEGIN_NAMESPACE + +class QCloudMessaging; +class QCloudMessagingEmbeddedKaltiotClient; + +class QCloudMessagingEmbeddedKaltiotClientPrivate +{ +public: + QCloudMessagingEmbeddedKaltiotClientPrivate() + { + m_running = false; + } + + ~QCloudMessagingEmbeddedKaltiotClientPrivate() = default; + + bool m_running; + QString m_uuid; + QString m_address; + QString m_version; + QString m_customer_id; + QStringList m_channels; + QString m_rid; + QSettings m_client_settings; + QThread m_clientThread; + QTimer m_threadTimer; + ks_gw_client_instance_t m_kaltiot_client_instance; +}; + +QT_END_NAMESPACE + +#endif // QCLOUDMESSAGINGCLIENT_P_H diff --git a/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotprovider.cpp b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotprovider.cpp new file mode 100644 index 0000000..dcb4129 --- /dev/null +++ b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotprovider.cpp @@ -0,0 +1,486 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcloudmessagingembeddedkaltiotprovider.h" +#include "qcloudmessagingembeddedkaltiotprovider_p.h" + +#ifdef ANDROID_OS +#include <QtAndroid> +#include "jni.h" +#endif + +QT_BEGIN_NAMESPACE + +/** + * @brief QCloudMessagingProvider + * @abstract Make the smart iot class accessible outside of the class for callback msgs. + */ + +static QCloudMessagingEmbeddedKaltiotProvider *m_KaltiotServiceProvider; + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::QCloudMessagingEmbeddedKaltiotProvider + */ +QCloudMessagingEmbeddedKaltiotProvider::QCloudMessagingEmbeddedKaltiotProvider(QObject *parent) : + QCloudMessagingProvider(parent), + d(new QCloudMessagingEmbeddedKaltiotProviderPrivate) +{ + m_KaltiotServiceProvider = this; + connect(&d->m_restInterface, &QCloudMessagingEmbeddedKaltiotRest::remoteClientsReceived, + this, &QCloudMessagingEmbeddedKaltiotProvider::remoteClientsReceived); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::~QCloudMessagingEmbeddedKaltiotProvider + */ +QCloudMessagingEmbeddedKaltiotProvider::~QCloudMessagingEmbeddedKaltiotProvider() +{ + deregisterProvider(); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::registerProvider + * \param serviceID + * \param parameters + * \return + */ +bool QCloudMessagingEmbeddedKaltiotProvider::registerProvider(const QString &serviceID, + const QVariantMap ¶meters) +{ + d->m_serviceID = serviceID; + + QCloudMessagingProvider::registerProvider(serviceID, parameters); + + setServiceState(QtCloudMessagingProviderRegistered); + + // Get the API key for HTTP communication + d->m_key = parameters.value(QStringLiteral("API_KEY")).toString(); + d->m_restInterface.setAuthKey(d->m_key); + + return QtCloudMessagingProviderRegistered; +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::deregisterProvider + * \return + */ +void QCloudMessagingEmbeddedKaltiotProvider::deregisterProvider() +{ + QCloudMessagingProvider::deregisterProvider(); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::setServiceState + * \param service_mode + * \return + */ +QCloudMessagingProvider::CloudMessagingProviderState QCloudMessagingEmbeddedKaltiotProvider::setServiceState(QCloudMessagingProvider::CloudMessagingProviderState service_mode) +{ + if (getServiceState() != QtCloudMessagingProviderNotRegistered) { + return QCloudMessagingProvider::setServiceState(service_mode); + } + return QtCloudMessagingProviderNotRegistered; +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::connectClient + * \param clientId + * \param parameters + * \return + */ +QString QCloudMessagingEmbeddedKaltiotProvider::connectClient(const QString &clientId, + const QVariantMap ¶meters) +{ + if (!providerId().isEmpty()) { + QCloudMessagingEmbeddedKaltiotClient *serviceClient = new QCloudMessagingEmbeddedKaltiotClient(); + + QString retval = connectClientToProvider(clientId, parameters, serviceClient); + +#ifdef ANDROID_OS + QtAndroid::androidActivity().callMethod<void>("init_kaltiot_wrapper", "()V"); +#endif + return retval; + } + return QString(); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::sendMessage + * \param msg + * \param clientId + * \param clientToken + * \param channel + * \return + */ +bool QCloudMessagingEmbeddedKaltiotProvider::sendMessage(const QByteArray &msg, + const QString &clientId, + const QString &clientToken, + const QString &channel) +{ + // Is this local client? + if (!clientId.isEmpty()) { + + if (getKaltiotClient(clientId) && clientToken.isEmpty()) { + getKaltiotClient(clientId)->messageReceived(clientId, msg); + return true; + } + + // No, not local. Its somewhere out there + } else { + + if (!clientToken.isEmpty() && channel.isEmpty()) { + + // Publish message to server via kaltiot SDK + QCloudMessagingEmbeddedKaltiotClient *tempClient = + (QCloudMessagingEmbeddedKaltiotClient *) clients()->first(); + + if (tempClient) + return tempClient->sendMessage(msg, clientToken, QString()); + } + + // Send to known device by using rest api - by giving not empty string to channel + if (!clientToken.isEmpty() && !channel.isEmpty()) + return d->m_restInterface.sendDataToDevice(clientToken, msg); + + // Broadcast to subscribed channel! + if (clientToken.isEmpty() && !channel.isEmpty()) + return d->m_restInterface.sendBroadcast(channel, msg); + } + + return false; +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::disconnectClient + * \param clientId + * \param parameters + * \return + */ +void QCloudMessagingEmbeddedKaltiotProvider::disconnectClient( + const QString &clientId, + const QVariantMap ¶meters) +{ + QCloudMessagingProvider::disconnectClient(clientId, parameters); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::clients + * \return + */ +QMap <QString, QCloudMessagingClient*> *QCloudMessagingEmbeddedKaltiotProvider::clients() +{ + return QCloudMessagingProvider::clients(); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::remoteClients + * \return + */ +bool QCloudMessagingEmbeddedKaltiotProvider::remoteClients() +{ + // Requesting remote clients via REST APi interface. + return d->m_restInterface.getAllDevices(); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::setClientToken + * \param client + * \param uuid + */ +void QCloudMessagingEmbeddedKaltiotProvider::setClientToken(const QString &client, + const QString &uuid) +{ + getKaltiotClient(client)->setClientToken(uuid); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::cloudMessageReceived + * \param client + * \param message + */ +void QCloudMessagingEmbeddedKaltiotProvider::cloudMessageReceived(const QString &client, + const QByteArray &message) +{ + getKaltiotClient(client)->cloudMessageReceived(client, message); + +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::subscribeToChannel + * \param channel + * \param clientId + * \return + */ +bool QCloudMessagingEmbeddedKaltiotProvider::subscribeToChannel(const QString &channel, + const QString &clientId) +{ + if (getKaltiotClient(clientId)) { + return getKaltiotClient(clientId)->subscribeToChannel(channel); + } + return false; +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::unsubscribeFromChannel + * \param channel + * \param clientId + * \return + */ +bool QCloudMessagingEmbeddedKaltiotProvider::unsubscribeFromChannel( + const QString &channel, + const QString &clientId) +{ + if (getKaltiotClient(clientId)) { + return getKaltiotClient(clientId)->unsubscribeFromChannel(channel); + } + return false; +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotProvider::getKaltiotClient + * \param clientId + * \return + */ +QCloudMessagingEmbeddedKaltiotClient *QCloudMessagingEmbeddedKaltiotProvider:: + getKaltiotClient(const QString &clientId) +{ + return (QCloudMessagingEmbeddedKaltiotClient *)client(clientId); +} + +/*** CALLBACK IMPLEMENTATIONS AGAINST KALTIOT SMART IOT LIBRARY */ +/*! + * \brief ks_gw_client_notification_cb + * Handles the callback function from the backend daemon. + * Informs the incoming notification / message from the server. + * \param address + * \param payload + * \param payload_length + * \param payload_type + * \param msg_id + * \param msg_id_length + */ +void ks_gw_client_notification_cb(const char *address, const char *payload, + const uint16_t payload_length, + const payload_type_t payload_type, + const char *msg_id, + const uint16_t msg_id_length) +{ + Q_UNUSED(payload_type); + Q_UNUSED(msg_id); + Q_UNUSED(msg_id_length); + + QString client = address != nullptr ? QString::fromLatin1(address) : QString(); + QByteArray b_payload = payload != nullptr ? QByteArray(payload, + payload_length) : QString().toLatin1(); + //QString msg = QString::fromLatin1(b_payload); + + if (!client.isEmpty()) + m_KaltiotServiceProvider->cloudMessageReceived(client, b_payload); +} + +/*! + * \brief ks_gw_client_state_changed_cb + * Handles the callback function from the backend daemon. + * Gets the state and forwards it to right client. + * \param state + * \param error + */ +void ks_gw_client_state_changed_cb(KaltiotSmartState state, KaltiotSmartError error) +{ + Q_UNUSED(error); + + // State related to client - assuming first client + QCloudMessagingEmbeddedKaltiotClient *firstClient = (QCloudMessagingEmbeddedKaltiotClient *)m_KaltiotServiceProvider->clients()->first(); + emit firstClient->clientStateChanged(firstClient->clientId(), state); + +} + +/*! + * \brief ks_gw_client_rid_cb + * Handles the callback function from the backend daemon. + * Gets the token and forwards it to right client. + * \param address + * \param rid + * \param secret + */ +void ks_gw_client_rid_cb(const char *address, const char *rid, + const char *secret) +{ + if (!address) address = "nullptr"; + if (!rid) rid = "nullptr"; + if (!secret) secret = "nullptr"; + + m_KaltiotServiceProvider->setClientToken(QString::fromLatin1(address), QString::fromLatin1(rid)); + +} + +#ifdef ANDROID_OS + +/*! + * \brief fromJavaOnStateChanged + * Handles the Android Kaltiot daemon message through JNI interface. + * Informs the client state change. + * \param env + * \param thiz + * \param address + * \param state + */ +static void fromJavaOnStateChanged(JNIEnv *env, jobject thiz, jstring address, jstring state) +{ + Q_UNUSED(env) + Q_UNUSED(thiz) + + QAndroidJniObject _address = address; + QAndroidJniObject _state = state; + + ks_gw_client_state_changed_cb((KaltiotSmartState)_state.toString().toInt(), + (KaltiotSmartError) 0); +} + +/*! + * \brief fromJavaOnRidChanged + * Handles the Android Kaltiot daemon message through JNI interface. + * Informs the client token change. + * \param env + * \param thiz + * \param address + * \param rid + */ +static void fromJavaOnRidChanged(JNIEnv *env, jobject thiz, jstring address, jstring rid) +{ + Q_UNUSED(env) + Q_UNUSED(thiz) + + + QAndroidJniObject _address = address; + QAndroidJniObject _rid = rid; + + ks_gw_client_rid_cb(_address.toString().toLatin1(), _rid.toString().toLatin1(), nullptr); + +} + +/*! + * \brief fromJavaOnAppIdChanged + * Handles the Android Kaltiot daemon message through JNI interface. + * Informs the application id string change. + * \param env + * \param thiz + * \param address + * \param appid + */ +static void fromJavaOnAppIdChanged(JNIEnv *env, jobject thiz, jstring address, jstring appid) +{ + Q_UNUSED(env) + Q_UNUSED(thiz) + + QAndroidJniObject _address = address; + QAndroidJniObject _appid = appid; + +} + +/*! + * \brief fromJavaOnNotification + * Handles the Android Kaltiot daemon message through JNI interface. + * Informs the incoming notification / message from the server. + * \param env + * \param thiz + * \param address + * \param payload + * \param msg + * \param payload_length + * \param payload_type + */ +static void fromJavaOnNotification(JNIEnv *env, jobject thiz, jstring address, jstring payload, + jstring msg, jint payload_length, jint payload_type) +{ + Q_UNUSED(env) + Q_UNUSED(thiz) + + const char *_payload = env->GetStringUTFChars(payload, JNI_FALSE); + + const char *_address = env->GetStringUTFChars(address, JNI_FALSE); + const char *_msg = env->GetStringUTFChars(msg, JNI_FALSE); + ks_gw_client_notification_cb(_address, + _payload, + payload_length, + (payload_type_t)payload_type, + _msg, + sizeof(_msg)); + +} + +static JNINativeMethod methods[] { + //{"native_notification_callback", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II;)V", reinterpret_cast<void *>(fromJavaOnNotification)}, + {"native_state_callback", "(Ljava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void *>(fromJavaOnStateChanged)}, + {"native_rid_callback", "(Ljava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void *>(fromJavaOnRidChanged)}, + {"native_appid_callback", "(Ljava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void *>(fromJavaOnAppIdChanged)}, + +}; + +extern "C" +{ + + JNIEXPORT void JNICALL + Java_com_snowgrains_radarsensor_QtApp_native_1notification_1callback__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2II( + JNIEnv *env, jobject thiz, jstring address, jstring payload, jstring msg, jint payload_length, + jint payload_type) + { + env = env; + const char *_payload = payload != nullptr ? env->GetStringUTFChars(payload, JNI_FALSE) : nullptr; + const char *_address = address != nullptr ? env->GetStringUTFChars(address, JNI_FALSE) : nullptr; + const char *_msg = msg != nullptr ? env->GetStringUTFChars(msg, JNI_FALSE) : nullptr; + ks_gw_client_notification_cb(_address, + _payload, + payload_length, + (payload_type_t)payload_type, + _msg, + sizeof(_msg)); + } + + JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) + { + + JNIEnv *env; + if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_4) != JNI_OK) { + return JNI_FALSE; + } + jclass clazz = env->FindClass("com/snowgrains/radarsensor/QtApp"); + if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) < 0) { + return JNI_FALSE; + } + return JNI_VERSION_1_4; + } +} +#endif + +/** CALLBACK IMPLEMENTATIONS ENDED ***/ + +// Provide link to main - which will be in the app using this service. +extern int main(int argc, char *argv[]); + +QT_END_NAMESPACE diff --git a/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotprovider.h b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotprovider.h new file mode 100644 index 0000000..705c08a --- /dev/null +++ b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotprovider.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KALTIOTPUSHSERVICE_H +#define KALTIOTPUSHSERVICE_H + +#include <QtCloudMessaging/QtCloudMessaging> +#include <QtCloudMessaging/qtcloudmessagingglobal.h> +#include <QtCloudMessaging/qcloudmessagingrestapi.h> +#include <QtCloudMessagingEmbeddedKaltiot/qcloudmessagingembeddedkaltiotclient.h> + +#include <QObject> +#include <QVariantMap> +#include <QScopedPointer> + +QT_BEGIN_NAMESPACE + +class QCloudMessagingEmbeddedKaltiotProviderPrivate; +class Q_CLOUDMESSAGING_EXPORT QCloudMessagingEmbeddedKaltiotProvider : public + QCloudMessagingProvider +{ + Q_OBJECT +public: + + explicit QCloudMessagingEmbeddedKaltiotProvider(QObject *parent = nullptr); + ~QCloudMessagingEmbeddedKaltiotProvider(); + + //! Qt Cloud messaging client virtual functions + virtual bool registerProvider(const QString &providerId, + const QVariantMap ¶meters = QVariantMap()) override; + + virtual void deregisterProvider() override; + + virtual QString connectClient(const QString &clientId, + const QVariantMap ¶meters = QVariantMap()) override; + + virtual void disconnectClient(const QString &clientId, + const QVariantMap ¶meters = QVariantMap()) override; + + virtual bool sendMessage(const QByteArray &msg, const QString &clientId = QString(), + const QString &clientToken = QString(), + const QString &channel = QString()) override; + + virtual QCloudMessagingProvider::CloudMessagingProviderState setServiceState( + QCloudMessagingProvider::CloudMessagingProviderState state) override; + + virtual QMap <QString, QCloudMessagingClient *> *clients() override; + + virtual bool subscribeToChannel(const QString &channel, + const QString &clientId = QString()) override; + + virtual bool unsubscribeFromChannel(const QString &channel, + const QString &clientId = QString()) override; + + virtual bool remoteClients() override; + + /* KALTIOT SPECIFIC FUNCTIONS */ + void cloudMessageReceived(const QString &client, const QByteArray &message); + QCloudMessagingEmbeddedKaltiotClient *getKaltiotClient(const QString &clientId); + + void setClientToken(const QString &client, const QString &uuid); + +private: + QScopedPointer<QCloudMessagingEmbeddedKaltiotProviderPrivate> d; + +}; + +QT_END_NAMESPACE + +#endif // KALTIOTPUSHSERVICE_H diff --git a/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotprovider_p.h b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotprovider_p.h new file mode 100644 index 0000000..d475ba8 --- /dev/null +++ b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotprovider_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLOUDMESSAGINGEMBEDDEDKALTIOTPROVIDER_P_H +#define QCLOUDMESSAGINGEMBEDDEDKALTIOTPROVIDER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +#include <QtCloudMessaging/qtcloudmessagingglobal.h> +#include <QtCloudMessagingEmbeddedKaltiot/QCloudMessagingEmbeddedKaltiotRest> + +#include <QStringList> + +#ifndef ANDROID_OS +#include "ks_gw_client.h" +#else +#include "ks_gw_client_android.h" +#endif + +QT_BEGIN_NAMESPACE + +class QCloudMessaging; + +class QCloudMessagingEmbeddedKaltiotProviderPrivate +{ +public: + QCloudMessagingEmbeddedKaltiotProviderPrivate() + { + } + + ~QCloudMessagingEmbeddedKaltiotProviderPrivate() = default; + + QStringList m_channels; + QString m_serviceID; + QString m_key; + + QCloudMessagingEmbeddedKaltiotRest m_restInterface; + ks_gw_client_instance_t *m_kaltiot_engine_instance; + +}; + +QT_END_NAMESPACE + +#endif // QCLOUDMESSAGINGEMBEDDEDKALTIOTPROVIDER_P_H diff --git a/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotrest.cpp b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotrest.cpp new file mode 100644 index 0000000..141e54e --- /dev/null +++ b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotrest.cpp @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtCloudMessaging/QtCloudMessaging> +#include "qtcloudmessagingglobal.h" +#include "qcloudmessagingembeddedkaltiotrest.h" + +#include <QObject> +#include <QByteArray> + +QT_BEGIN_NAMESPACE + +/* REST API INTERFACE */ +const QString SERVER_ADDRESS = QStringLiteral("https://restapi.torqhub.io"); + +/*! + * \brief QCloudMessagingEmbeddedKaltiotRest::getAllDevices + * \return + */ +bool QCloudMessagingEmbeddedKaltiotRest::getAllDevices() +{ + QString url = SERVER_ADDRESS + "/rids/identities" + "?ApiKey=" + m_auth_key; + QUrl uri(url); + QNetworkRequest request(uri); + + request.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain; charset=ISO-8859-1"); + + return sendMessage(GET_MSG, REQ_GET_ALL_DEVICES, request, "", true, ""); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotRest::sendDataToDevice + * \param rid + * \param data + * \return + */ +bool QCloudMessagingEmbeddedKaltiotRest::sendDataToDevice(const QString &rid, const QByteArray &data) +{ + + QString url = SERVER_ADDRESS + "/rids/" + rid + "?ApiKey=" + m_auth_key; + QUrl uri(url); + QNetworkRequest request(uri); + + request.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain; charset=ISO-8859-1"); + + return sendMessage(POST_MSG, REQ_SEND_DATA_TO_DEVICE, request, data, true, ""); +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotRest::sendBroadcast + * \param channel + * \param data + * \return + */ +bool QCloudMessagingEmbeddedKaltiotRest::sendBroadcast(const QString &channel, const QByteArray &data) +{ + + QString url = SERVER_ADDRESS + "/rids/channel/" + channel + "?ApiKey=" + m_auth_key; + QUrl uri(url); + QNetworkRequest request(uri); + request.setHeader(QNetworkRequest::ContentTypeHeader, "text/plain; charset=ISO-8859-1"); + + return sendMessage(POST_MSG, REQ_SEND_BROADCAST_DATA_TO_CHANNEL, request, data, true, ""); + +} + +/*! + * \brief QCloudMessagingEmbeddedKaltiotRest::xmlHttpRequestReply + * \param reply + */ +void QCloudMessagingEmbeddedKaltiotRest::xmlHttpRequestReply(QNetworkReply *reply) +{ + + getNetworkManager()->disconnect(SIGNAL(finished(QNetworkReply *))); + QString m_msg_uuid = reply->property("uuid").toString(); + int req_id = reply->property("req_id").toInt(); + + if (reply->error()) { + emit xmlHttpRequestError(reply->errorString()); + + } + + // Ok message, lets proceed. + + QByteArray data(reply->readAll()); + + switch (req_id) { + case REQ_GET_DEVICES_BY_CUSTOMER_ID: + + break; + case REQ_GET_ALL_DEVICES: { + Q_EMIT remoteClientsReceived(QString::fromUtf8(data)); + } + break; + case REQ_SEND_DATA_TO_DEVICE: + + break; + case REQ_SEND_BROADCAST_DATA_TO_CHANNEL: + + break; + case REQ_GET_DEVICE_INFO: + + break; + } + + reply->deleteLater(); + clearMessage(m_msg_uuid); + +} + +// Signals documentation +/*! + \fn QCloudMessagingEmbeddedKaltiotRest::remoteClientsReceived(const QString &clients) + This signal is triggered when the return value for requestRemoteClients + function is is received +. + \param response + Response data is based on the service and can be e.g. a list + of client tokens in QString format. +*/ +QT_END_NAMESPACE diff --git a/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotrest.h b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotrest.h new file mode 100644 index 0000000..3da3059 --- /dev/null +++ b/src/cloudmessagingembeddedkaltiot/qcloudmessagingembeddedkaltiotrest.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QCLOUDMESSAGINGEMBEDDEDKALTIOTREST_H +#define QCLOUDMESSAGINGEMBEDDEDKALTIOTREST_H + +#include <QtCloudMessaging/QtCloudMessaging> +#include <QtCloudMessaging/qtcloudmessagingglobal.h> +#include <QtCloudMessaging/qcloudmessagingrestapi.h> +#include <QtCloudMessagingEmbeddedKaltiot/qcloudmessagingembeddedkaltiotclient.h> +#include <QObject> + +QT_BEGIN_NAMESPACE + +class QCloudMessagingEmbeddedKaltiotRest : public QCloudMessagingRestApi +{ + Q_OBJECT +public: + enum KaltiotRESTRequests { + REQ_NO_REQ, + REQ_GET_DEVICES_BY_CUSTOMER_ID, + REQ_GET_ALL_DEVICES, + REQ_SEND_DATA_TO_DEVICE, + REQ_SEND_BROADCAST_DATA_TO_CHANNEL, + REQ_GET_DEVICE_INFO + }; + Q_ENUM(KaltiotRESTRequests) + + void setAuthKey(QString key) + { + m_auth_key = key; + } + + /* KALTIOT REST API + * + * Get Identities + * GET /rids/identities/customerId/:cust_id - Your device identities by customer id + * GET /rids/identities/paginStart/:paginStart/paginCount/:paginCount - Your devices identities with pagination + * GET /rids/identities/timeFrom/:timeFrom/timeTo/:timeTo - Your device identities by creation timestamps + * GET /rids/identities - All your devices identities + * + * Create persistence sessions + * POST /cn/:cn/data_stream - Create persistent web socket session to all your devices + * POST /rids/:rid/data_stream - Create persistent web socket session to single device + * + * Get data from devices + * GET /cn/:cn/data_stream/sessionId/:sessionId - Use persistent web socket to all your devices + * GET /cn/:cn/data_stream - Use non persistent web socket to all your devices + * GET /rids/:rid/data_stream/sessionId/:sessionId - Use Persistent web socket to single device + * GET /rids/:rid/data_stream - Use non persistent web socket to single device + * + * Send data to devices + * POST /rids/:rid - Send data to single device + * POST /rids/channel/:channel - Send data to group of devices + * + * Get Device Information + * GET /rids/:rid/presence - Get your device presence information + * + */ + + + /* getAllDevices implements + * GET /rids/identities - All your devices identities + */ + bool getAllDevices(); + + /* Implements + * POST /rids/:rid - Send data to single device + */ + bool sendDataToDevice(const QString &rid, const QByteArray &data); + + /* Implements + * POST /rids/channel/:channel - Send data to group of devices + */ + bool sendBroadcast(const QString &channel, const QByteArray &data); + + /* Error codes for requests */ + /** + * {"result": "<Error Message>"} + * 1 - InvalidJSON Json used in request was not valid + * 2 - RidNotFound RID used in request was not connected + * 3 - HandshakeFailure WebSocket handshake was unsuccessful + * 4 - MessageLost Message received by RestApi was lost, delivery to client cannot be guaranteed + * 5 - NoRoute Message received by RestApi was not able to deliver to client + * 6 - MalformedRequest Request received by RestApi was not properly formatted + * 7 - UriNotFound Request to URI which was made is not existing + * 8 - MethodNotAllowed Http method which was used to access URI is not allowed + * 9 - DeliveryFailure Message received by RestApi was not able to deliver to client + * 10 - UnAuthorized Apikey which was used was not accepted + */ + + void xmlHttpRequestReply(QNetworkReply *reply); + +Q_SIGNALS: + void remoteClientsReceived(const QString &clients); + +private: + QString m_auth_key; +}; + +QT_END_NAMESPACE + +#endif // QCLOUDMESSAGINGEMBEDDEDKALTIOTREST_H diff --git a/src/cloudmessagingfirebase/cloudmessagingfirebase.pro b/src/cloudmessagingfirebase/cloudmessagingfirebase.pro new file mode 100644 index 0000000..e9ad425 --- /dev/null +++ b/src/cloudmessagingfirebase/cloudmessagingfirebase.pro @@ -0,0 +1,51 @@ +TARGET = QtCloudMessagingFirebase +QT = core cloudmessaging +CONFIG += static +HEADERS += \ + qcloudmessagingfirebaseclient.h \ + qcloudmessagingfirebaseprovider.h \ + qcloudmessagingfirebaseclient_p.h \ + qcloudmessagingfirebaseprovider_p.h \ + qcloudmessagingfirebaserest.h + +SOURCES += \ + $$PWD/qcloudmessagingfirebaseclient.cpp \ + $$PWD/qcloudmessagingfirebaseprovider.cpp \ + qcloudmessagingfirebaserest.cpp + +# Check for GOOGLE_FIREBASE_SDK environment variable +ENV_GOOGLE_FIREBASE_SDK = $$(GOOGLE_FIREBASE_SDK) + +# Or define GOOGLE_FIREBASE_SDK path here +GOOGLE_FIREBASE_SDK = + +isEmpty(ENV_GOOGLE_FIREBASE_SDK) { + isEmpty(GOOGLE_FIREBASE_SDK) { + message("GOOGLE_FIREBASE_SDK" environment variable not detected!) + } +} + +INCLUDEPATH += $$(GOOGLE_FIREBASE_SDK) +INCLUDEPATH += $$(GOOGLE_FIREBASE_SDK)/include + +android { + QT += androidextras + + LIBS += $$(GOOGLE_FIREBASE_SDK)/libs/android/armeabi-v7a/gnustl/libmessaging.a + LIBS += $$(GOOGLE_FIREBASE_SDK)/libs/android/armeabi-v7a/gnustl/libapp.a + +} else: macos { + LIBS += -F$$(GOOGLE_FIREBASE_SDK)/frameworks/darwin \ + -framework firebase \ + -framework firebase_messaging +} else: ios { + LIBS += -F$$(GOOGLE_FIREBASE_SDK)/frameworks/ios/universal \ + -framework firebase_messaging \ + -framework firebase \ + -framework Foundation \ + -framework UserNotifications \ + -framework UIKit \ + -framework CoreGraphics +} + +load(qt_module) diff --git a/src/cloudmessagingfirebase/qcloudmessagingfirebaseclient.cpp b/src/cloudmessagingfirebase/qcloudmessagingfirebaseclient.cpp new file mode 100644 index 0000000..2ef4921 --- /dev/null +++ b/src/cloudmessagingfirebase/qcloudmessagingfirebaseclient.cpp @@ -0,0 +1,336 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcloudmessagingfirebaseclient.h" +#include "qcloudmessagingfirebaseclient_p.h" + +#if defined(Q_OS_ANDROID) +#include <QtAndroid> +#include <QtAndroidExtras> +#include <QAndroidJniObject> +#elif defined(Q_OS_DARWIN) +extern "C" { +#include <objc/objc.h> +} // extern "C" +#endif // __ANDROID__ + +QT_BEGIN_NAMESPACE + +extern void LogMessage(const char *format, ...); +static QCloudMessagingFirebaseClient *m_client_pointer; + +/*! + * \brief QCloudMessagingFirebaseClient::QCloudMessagingFirebaseClient + */ +QCloudMessagingFirebaseClient::QCloudMessagingFirebaseClient(QObject *parent) : + QCloudMessagingClient(parent), + d(new QCloudMessagingFirebaseClientPrivate) +{ +} + +/*! + * \brief QCloudMessagingFirebaseClient::~QCloudMessagingFirebaseClient + */ +QCloudMessagingFirebaseClient::~QCloudMessagingFirebaseClient() +{ +} + +/*! + * \brief QCloudMessagingFirebaseClient::connectClient + * \param clientId + * \param parameters + * \return + */ +QString QCloudMessagingFirebaseClient::connectClient(const QString &clientId, + const QVariantMap ¶meters) +{ + QCloudMessagingClient::connectClient(clientId, parameters); + // Call parent function to setup service ids and states. + + // Setup Firebase app for the client. +#if defined(__ANDROID__) + d->m_firebaseApp = ::firebase::App::Create(::firebase::AppOptions(), QAndroidJniEnvironment(), + QtAndroid::androidActivity().object()); + +#endif +#if defined(__APPLE__) + d->m_firebaseApp = ::firebase::App::Create(::firebase::AppOptions()); + +#endif // defined(__ANDROID__) + m_client_pointer = this; + + d->m_firebase_initializer.Initialize(d->m_firebaseApp, + nullptr, [](::firebase::App * fapp, void *) { + LogMessage("Try to initialize Firebase Messaging"); + return ::firebase::messaging::Initialize( + *fapp, + (::firebase::messaging::Listener *)m_client_pointer); + }); + + while (d->m_firebase_initializer.InitializeLastResult().status() != + firebase::kFutureStatusComplete) { + + LogMessage("Firebase: InitializeLastResult wait..."); + } + + setClientId(clientId); + return clientId; +} + +/*! + * \brief QCloudMessagingFirebaseClient::sendMessage + * \param msg + * \param send_to_device + * \param send_to_channel + * \return + */ +bool QCloudMessagingFirebaseClient::sendMessage(const QByteArray &msg, const QString &clientToken, + const QString &channel) +{ + Q_UNUSED(channel) + + ::firebase::messaging::Message message; + + QString message_to = clientToken + "@gcm.googleapis.com"; + + message.to = message_to.toStdString(); + + //TODO: USE Uuid Qt generator + message.message_id = QString("uniqueId" + QString::number(rand() * 10000)).toStdString(); + + //TODO: QString to std map conversion from the input message + Q_UNUSED(msg); + // message.data + + // TODO: Use specific client parameters for time to live + message.time_to_live = 1000000 ;//TIME_TO_LIVE; + ::firebase::messaging::Send(message); + + return true; +} + +/*! + * \brief QCloudMessagingFirebaseClient::disconnectClient + * \return + */ +void QCloudMessagingFirebaseClient::disconnectClient() +{ + QCloudMessagingClient::disconnectClient(); +} + +/*! + * \brief QCloudMessagingFirebaseClient::cloudMessageReceived + * \param client + * \param message + */ +void QCloudMessagingFirebaseClient::cloudMessageReceived(const QString &client, + const QByteArray &message) +{ + emit messageReceived(client, message); +} + +/*! + * \brief QCloudMessagingFirebaseClient::OnTokenReceived + * \param token + */ +void QCloudMessagingFirebaseClient::OnTokenReceived(const char *token) +{ + d->m_token = QString::fromLatin1(token); +} + +/*! + * \brief QCloudMessagingFirebaseClient::OnMessage + * \param message + */ +void QCloudMessagingFirebaseClient::OnMessage(const::firebase::messaging::Message &message) +{ + d->m_last_firebase_message = message; + emit messageReceived(clientId(), parseMessage(d->m_last_firebase_message).toUtf8()); +} + +/*! + * \brief QCloudMessagingFirebaseClient::setClientToken + * \param uuid + */ +void QCloudMessagingFirebaseClient::setClientToken(const QString &uuid) +{ + d->m_token = uuid; + emit clientTokenReceived(d->m_token); +} + +/*! + * \brief QCloudMessagingFirebaseClient::parseMessage + * \param msg_map + * \return + */ +QString QCloudMessagingFirebaseClient::parseMessage(::firebase::messaging::Message msg_map) +{ + QString msg; + msg = QString::fromLatin1("{"); + bool dotSign = false; + + if (!msg_map.from.empty()) { + if (dotSign) msg += QString::fromLatin1(","); + msg += QString::fromLatin1("\"from\":\"") + QString::fromLatin1(msg_map.from.c_str()) + "\""; + dotSign = true; + } + if (!msg_map.error.empty()) { + if (dotSign) msg += QString::fromLatin1(","); + msg += QString::fromLatin1("\"error\":\"") + QString::fromLatin1(msg_map.error.c_str()) + "\""; + dotSign = true; + } + if (!msg_map.message_id.empty()) { + if (dotSign) msg += QString::fromLatin1(","); + msg += QString::fromLatin1("\"message_id\":\"") + QString::fromLatin1( + msg_map.message_id.c_str()) + "\""; + dotSign = true; + } + + if (msg_map.notification) { + + if (dotSign) msg += QString::fromLatin1(","); + + msg += QString::fromLatin1("\"notification\":{"); + + if (msg_map.notification_opened) + msg += QString::fromLatin1("\"notification_opened\":true"); + else + msg += QString::fromLatin1("\"notification_opened\":false"); + + if (!msg_map.notification->title.empty()) + msg += QString::fromLatin1(",\"title\":\"") + QString::fromLatin1( + msg_map.notification->title.c_str()) + QString::fromLatin1("\""); + + if (!msg_map.notification->body.empty()) + msg += QString::fromLatin1(",\"body\":\"") + QString::fromLatin1(msg_map.notification->body.c_str()) + + QString::fromLatin1("\""); + + if (!msg_map.notification->icon.empty()) + msg += QString::fromLatin1(",\"icon\":\"") + QString::fromLatin1(msg_map.notification->icon.c_str()) + + QString::fromLatin1("\""); + + if (!msg_map.notification->tag.empty()) + msg += QString::fromLatin1(",\"tag\":\"") + QString::fromLatin1(msg_map.notification->tag.c_str()) + + QString::fromLatin1("\""); + + if (!msg_map.notification->color.empty()) + msg += QString::fromLatin1(",\"color\":\"") + QString::fromLatin1( + msg_map.notification->color.c_str()) + QString::fromLatin1("\""); + + if (!msg_map.notification->sound.empty()) + msg += QString::fromLatin1(",\"sound\":\"") + QString::fromLatin1( + msg_map.notification->sound.c_str()) + QString::fromLatin1("\""); + + if (!msg_map.notification->click_action.empty()) + msg += QString::fromLatin1(",\"click_action\":\"") + QString::fromLatin1( + msg_map.notification->click_action.c_str()) + QString::fromLatin1("\""); + + msg += QString::fromLatin1("}"); + + dotSign = true; + } + if (msg_map.data.size() > 0) { + if (dotSign) msg += QString::fromLatin1(","); + + dotSign = false; + + msg += QString::fromLatin1("\"data\":{"); + + for (const auto &field : msg_map.data) { + + if (!field.first.empty() && !field.second.empty()) { + if (dotSign) msg += QString::fromLatin1(","); + + msg += QString::fromLatin1("\"") + QString::fromStdString(field.first) + QString::fromLatin1("\":") + + QString::fromStdString(field.second); + + dotSign = true; + } + } + msg += QString::fromLatin1("}"); + } + msg += QString::fromLatin1("}"); + return msg; +} + +/*! + * \brief QCloudMessagingFirebaseClient::flushMessageQueue + * \return + */ +bool QCloudMessagingFirebaseClient::flushMessageQueue() +{ + if (!d->m_last_firebase_message.message_id.empty()) { + emit messageReceived(clientId(), parseMessage(d->m_last_firebase_message).toUtf8()); + } + return true; +} + +/*! + * \brief QCloudMessagingFirebaseClient::subscribeToChannel + * \param channel + * \return + */ +bool QCloudMessagingFirebaseClient::subscribeToChannel(const QString &channel) +{ + ::firebase::messaging::Subscribe(channel.toLatin1()); + return true; +} + +/*! + * \brief QCloudMessagingFirebaseClient::unsubscribeFromChannel + * \param channel + * \return + */ +bool QCloudMessagingFirebaseClient::unsubscribeFromChannel(const QString &channel) +{ + ::firebase::messaging::Unsubscribe(channel.toLatin1()); + return true; +} + +/*! + * \brief QCloudMessagingFirebaseClient::clientToken + * \return + */ +QString QCloudMessagingFirebaseClient::clientToken() +{ + return d->m_token; +} + +/*! + * \brief QCloudMessagingFirebaseClient::clientUuid + * \return + */ +QString QCloudMessagingFirebaseClient::clientUuid() +{ + return d->m_token; +} + +// Provide link to main - which will be in the app using this service. +extern int main(int argc, char *argv[]); + +QT_END_NAMESPACE diff --git a/src/cloudmessagingfirebase/qcloudmessagingfirebaseclient.h b/src/cloudmessagingfirebase/qcloudmessagingfirebaseclient.h new file mode 100644 index 0000000..4679c0a --- /dev/null +++ b/src/cloudmessagingfirebase/qcloudmessagingfirebaseclient.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCloudMessagingFirebaseClient_H +#define QCloudMessagingFirebaseClient_H + +#include <QtCloudMessaging/QtCloudMessaging> +#include "firebase/app.h" +#include "firebase/messaging.h" +#include "firebase/util.h" +#include <QObject> +#include <QVariantMap> +#include <QScopedPointer> + +QT_BEGIN_NAMESPACE + +class QCloudMessagingFirebaseClientPrivate; + +class QCloudMessagingFirebaseClient: public QCloudMessagingClient, firebase::messaging::Listener +{ + +public: + + explicit QCloudMessagingFirebaseClient(QObject *parent = nullptr); + + ~QCloudMessagingFirebaseClient(); + + //! Firebase virtual functions + + virtual void OnMessage(const ::firebase::messaging::Message &message) override; + + virtual void OnTokenReceived(const char *token) override; + + + //! Qt Cloud messaging client virtual functions + + virtual bool flushMessageQueue() override; + + virtual QString connectClient(const QString &clientId, + const QVariantMap ¶meters = QVariantMap()) override; + + virtual void disconnectClient() override; + + virtual bool subscribeToChannel(const QString &channel) override; + + virtual bool unsubscribeFromChannel(const QString &channel) override; + + QString clientToken() override; + + QString clientUuid(); + + bool sendMessage(const QByteArray &msg, + const QString &clientToken = QString(), + const QString &channel = QString()) override; + + void cloudMessageReceived(const QString &client, + const QByteArray &message) override; + + void setClientToken(const QString &uuid) override; + +private: + QString parseMessage(firebase::messaging::Message msg_map); + + QScopedPointer<QCloudMessagingFirebaseClientPrivate> d; +}; + +QT_END_NAMESPACE + +#endif // QCloudMessagingFirebaseClient_H diff --git a/src/cloudmessagingfirebase/qcloudmessagingfirebaseclient_p.h b/src/cloudmessagingfirebase/qcloudmessagingfirebaseclient_p.h new file mode 100644 index 0000000..70f0d8d --- /dev/null +++ b/src/cloudmessagingfirebase/qcloudmessagingfirebaseclient_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLOUDMESSAGINGFIREBASECLIENT_P_H +#define QCLOUDMESSAGINGFIREBASECLIENT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qtcloudmessagingglobal.h> +#include "qcloudmessagingfirebaseclient.h" +#include "qcloudmessagingfirebaserest.h" +#include "firebase/app.h" +#include "firebase/messaging.h" +#include "firebase/util.h" + + +QT_BEGIN_NAMESPACE + +class QCloudMessaging; + +class QCloudMessagingFirebaseClientPrivate +{ +public: + QCloudMessagingFirebaseClientPrivate() + { + } + + ~QCloudMessagingFirebaseClientPrivate() = default; + + QString m_uuid; + QString m_token; + + ::firebase::App *m_firebaseApp; + ::firebase::ModuleInitializer m_firebase_initializer; + ::firebase::messaging::Message m_last_firebase_message; + +}; + +QT_END_NAMESPACE + +#endif // QCLOUDMESSAGINGFIREBASECLIENT_P_H diff --git a/src/cloudmessagingfirebase/qcloudmessagingfirebaseprovider.cpp b/src/cloudmessagingfirebase/qcloudmessagingfirebaseprovider.cpp new file mode 100644 index 0000000..065a00a --- /dev/null +++ b/src/cloudmessagingfirebase/qcloudmessagingfirebaseprovider.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcloudmessagingfirebaseprovider.h" +#include "qcloudmessagingfirebaseprovider_p.h" + +#include "firebase/app.h" +#include "firebase/messaging.h" +#include "firebase/util.h" + +QT_BEGIN_NAMESPACE + +static QCloudMessagingFirebaseProvider *m_FirebaseServiceProvider; + +/*! + * \brief LogMessage + * \param format + */ +void LogMessage(const char *format, ...) +{ + static const int kLineBufferSize = 100; + char buffer[kLineBufferSize + 2]; + + va_list list; + va_start(list, format); + int string_len = vsnprintf(buffer, kLineBufferSize, format, list); + string_len = string_len < kLineBufferSize ? string_len : kLineBufferSize; + // append a linebreak to the buffer: + buffer[string_len] = '\n'; + buffer[string_len + 1] = '\0'; + va_end(list); +} + +/*! + * \brief QCloudMessagingFirebaseProvider::QCloudMessagingFirebaseProvider + */ +QCloudMessagingFirebaseProvider::QCloudMessagingFirebaseProvider(QObject *parent) : + QCloudMessagingProvider(parent), + d(new QCloudMessagingFirebaseProviderPrivate) +{ + m_FirebaseServiceProvider = this; +} + +/*! + * \brief QCloudMessagingFirebaseProvider::~QCloudMessagingFirebaseProvider + */ +QCloudMessagingFirebaseProvider::~QCloudMessagingFirebaseProvider() +{ + deregisterProvider(); +} + +/*! + * \brief QCloudMessagingFirebaseProvider::registerProvider + * \param providerId + * \param parameters + * \return + */ +bool QCloudMessagingFirebaseProvider::registerProvider(const QString &providerId, + const QVariantMap ¶meters) +{ + + QCloudMessagingProvider::registerProvider(providerId, parameters); + + setServiceState(QtCloudMessagingProviderRegistered); + + // Get the API key for HTTP communication + d->m_key = parameters.value(QStringLiteral("SERVER_API_KEY")).toString(); + d->m_restInterface.setAuthKey(d->m_key); + + return true; +} + +/*! + * \brief QCloudMessagingFirebaseProvider::deregisterProvider + * \return + */ +void QCloudMessagingFirebaseProvider::deregisterProvider() +{ + ::firebase::messaging::Terminate(); + QCloudMessagingProvider::deregisterProvider(); +} + +/*! + * \brief QCloudMessagingFirebaseProvider::setServiceState + * \param service_mode + * \return + */ +QCloudMessagingProvider::CloudMessagingProviderState QCloudMessagingFirebaseProvider::setServiceState(QCloudMessagingProvider::CloudMessagingProviderState service_mode) +{ + if (getServiceState() != QtCloudMessagingProviderNotRegistered) { + return QCloudMessagingProvider::setServiceState(service_mode); + } + + return QCloudMessagingProvider::QtCloudMessagingProviderNotRegistered; +} + +/*! + * \brief QCloudMessagingFirebaseProvider::connectClient + * \param clientId + * \param parameters + * \return + */ +QString QCloudMessagingFirebaseProvider::connectClient(const QString &clientId, + const QVariantMap ¶meters) +{ + if (!providerId().isEmpty()) { + QCloudMessagingFirebaseClient *serviceClient = new QCloudMessagingFirebaseClient(); + QString retval = connectClientToProvider(clientId, parameters, serviceClient); + return retval; + } + return QString(); +} + + +/*! + * \brief QCloudMessagingFirebaseProvider::sendMessage + * \param msg + * \param clientId + * \param send_to_device + * \param send_to_channel + * \return + */ +bool QCloudMessagingFirebaseProvider::sendMessage(const QByteArray &msg, const QString &clientId, + const QString &clientToken, const QString &channel) +{ + //! Sending to internal client + if (!clientId.isEmpty() && clientToken.isEmpty() && channel.isEmpty()) { + + if (client(clientId)) { + client(clientId)->messageReceived(clientId, msg); + return true; + } + } else + //! Sending to device or channel out there, by using the client (e.g. in mobile) + if (!clientId.isEmpty() && (!clientToken.isEmpty() && !channel.isEmpty())) { + + if (client(clientId)) { + return client(clientId)->sendMessage(msg, clientToken, channel); + } + + } else { + //! Sending via rest api interface (SERVER side) + if (!channel.isEmpty()) + return d->m_restInterface.sendBroadcast(channel, msg); + + if (!clientToken.isEmpty()) + return d->m_restInterface.sendToDevice(clientToken, msg); + } + return false; +} + +/*! + * \brief QCloudMessagingFirebaseProvider::disconnectClient + * \param clientId + * \param parameters + * \return + */ +void QCloudMessagingFirebaseProvider::disconnectClient(const QString &clientId, + const QVariantMap ¶meters) +{ + return QCloudMessagingProvider::disconnectClient(clientId, parameters); +} + +/*! + * \brief QCloudMessagingFirebaseProvider::clients + * \return + */ +QMap <QString, QCloudMessagingClient *> *QCloudMessagingFirebaseProvider::clients() +{ + return QCloudMessagingProvider::clients(); +} + +/*! + * \brief QCloudMessagingFirebaseProvider::setClientToken + * \param client + * \param uuid + */ +void QCloudMessagingFirebaseProvider::setClientToken(const QString &clientId, const QString &uuid) +{ + client(clientId)->setClientToken(uuid); +} + +/*! + * \brief QCloudMessagingFirebaseProvider::cloudMessageReceived + * \param client + * \param message + */ +void QCloudMessagingFirebaseProvider::cloudMessageReceived(const QString &clientId, + const QByteArray &message) +{ + client(clientId)->messageReceived(clientId, message); +} + +/*! + * \brief QCloudMessagingFirebaseProvider::subscribeToChannel + * \param channel + * \param clientId + * \return + */ +bool QCloudMessagingFirebaseProvider::subscribeToChannel(const QString &channel, + const QString &clientId) +{ + if (!clientId.isEmpty()) + return client(clientId)->subscribeToChannel(channel); + + return true; +} + +/*! + * \brief QCloudMessagingFirebaseProvider::unsubscribeFromChannel + * \param channel + * \param clientId + * \return + */ +bool QCloudMessagingFirebaseProvider::unsubscribeFromChannel(const QString &channel, + const QString &clientId) +{ + if (!clientId.isEmpty()) + return client(clientId)->unsubscribeFromChannel(channel); + + return true; +} + +/*! + * \brief QCloudMessagingFirebaseProvider::clientToken + * \param clientId + * \return + */ +QString QCloudMessagingFirebaseProvider::clientToken(const QString &clientId) +{ + return client(clientId)->clientToken(); +} + +/*! + * \brief QCloudMessagingFirebaseProvider::remoteClients + * \return + */ +bool QCloudMessagingFirebaseProvider::remoteClients() +{ + return false; +} + +QT_END_NAMESPACE + + + diff --git a/src/cloudmessagingfirebase/qcloudmessagingfirebaseprovider.h b/src/cloudmessagingfirebase/qcloudmessagingfirebaseprovider.h new file mode 100644 index 0000000..30b3ce0 --- /dev/null +++ b/src/cloudmessagingfirebase/qcloudmessagingfirebaseprovider.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FIREBASESERVICE_H +#define FIREBASESERVICE_H + +#include <QtCloudMessaging/QtCloudMessaging> +#include <QtCloudMessaging/qcloudmessagingrestapi.h> +#include <QtCloudMessagingFirebase/qcloudmessagingfirebaseclient.h> +#include "firebase/app.h" +#include "firebase/messaging.h" +#include "firebase/util.h" +#include <QObject> +#include <QVariantMap> +#include <QByteArray> +#include <QScopedPointer> + +QT_BEGIN_NAMESPACE + +class QCloudMessagingFirebaseProviderPrivate; + +class QCloudMessagingFirebaseProvider : public QCloudMessagingProvider +{ + Q_OBJECT +public: + + explicit QCloudMessagingFirebaseProvider(QObject *parent = nullptr); + + ~QCloudMessagingFirebaseProvider(); + + virtual bool registerProvider(const QString &providerId, const QVariantMap ¶meters = QVariantMap()) override; + + virtual void deregisterProvider() override; + + virtual QCloudMessagingProvider::CloudMessagingProviderState setServiceState( + QCloudMessagingProvider::CloudMessagingProviderState state) override; + + virtual QString connectClient(const QString &clientId, const QVariantMap ¶meters = QVariantMap()) override; + + virtual void disconnectClient(const QString &clientId, const QVariantMap ¶meters = QVariantMap()) override; + + virtual bool sendMessage(const QByteArray &msg, const QString &clientId = QString(), + const QString &clientToken = QString(), + const QString &channel = QString()) override; + + + virtual bool subscribeToChannel(const QString &channel, const QString &clientId = QString()) override; + + virtual bool unsubscribeFromChannel(const QString &channel, const QString &clientId = QString()) override; + + QMap <QString, QCloudMessagingClient *> *clients() override; + + // Firefox server API tbd. + bool remoteClients() override; + + QString clientToken(const QString &clientId); + + void setClientToken(const QString &clientId, const QString &uuid); + + +private Q_SLOTS: + void cloudMessageReceived(const QString &clientId, const QByteArray &message); + +private: + QScopedPointer<QCloudMessagingFirebaseProviderPrivate> d; +}; + +QT_END_NAMESPACE + +#endif // FIREBASESERVICE_H diff --git a/src/cloudmessagingfirebase/qcloudmessagingfirebaseprovider_p.h b/src/cloudmessagingfirebase/qcloudmessagingfirebaseprovider_p.h new file mode 100644 index 0000000..e64f452 --- /dev/null +++ b/src/cloudmessagingfirebase/qcloudmessagingfirebaseprovider_p.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLOUDMESSAGINGFIREBASEPROVIDER_P_H +#define QCLOUDMESSAGINGFIREBASEPROVIDER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCloudMessaging/qtcloudmessagingglobal.h> +#include "qcloudmessagingfirebaseprovider.h" +#include "qcloudmessagingfirebaserest.h" + +QT_BEGIN_NAMESPACE + +class QCloudMessaging; + +class QCloudMessagingFirebaseProviderPrivate +{ +public: + QCloudMessagingFirebaseProviderPrivate() + { + } + + ~QCloudMessagingFirebaseProviderPrivate() = default; + + QStringList m_channels; + QString m_key; + FirebaseRestServer m_restInterface; +}; + +QT_END_NAMESPACE + +#endif // QCLOUDMESSAGINGFIREBASEPROVIDER_P_H diff --git a/src/cloudmessagingfirebase/qcloudmessagingfirebaserest.cpp b/src/cloudmessagingfirebase/qcloudmessagingfirebaserest.cpp new file mode 100644 index 0000000..df27b6a --- /dev/null +++ b/src/cloudmessagingfirebase/qcloudmessagingfirebaserest.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCloudMessaging/QtCloudMessaging> +#include "qtcloudmessagingglobal.h" +#include "qcloudmessagingfirebaserest.h" + +#include <QByteArray> + +/* REST API INTERFACE */ +const QString SERVER_ADDRESS = QStringLiteral("https://fcm.googleapis.com/fcm/send"); + +/*! + * \brief FirebaseRestServer::sendToDevice + * \param token + * \param data + * \return + */ +bool FirebaseRestServer::sendToDevice(const QString &token, const QByteArray &data) +{ + QString data_to_send = "{\"to\":\"" + token + "\",\"data\":" + QString::fromUtf8(data) + "}"; + QString url = SERVER_ADDRESS; + QUrl uri(url); + m_auth_key = "key=" + m_auth_key; + QNetworkRequest request(uri); + QString authHeader = QString::fromLatin1("Authorization"); + request.setHeader(QNetworkRequest::ContentTypeHeader, QString::fromLatin1("application/json")); + request.setRawHeader(authHeader.toLocal8Bit(), m_auth_key.toLocal8Bit()); + + return sendMessage(POST_MSG, + REQ_SEND_BROADCAST_DATA_TO_CHANNEL, + request, + data_to_send.toUtf8(), + true, + QString()); +} + +/*! + * \brief FirebaseRestServer::sendBroadcast + * \param channel + * \param data + * \return + */ +bool FirebaseRestServer::sendBroadcast(const QString &channel, const QByteArray &data) +{ + QString mod_data = QString::fromUtf8(data); + if (mod_data[0] == '{') + mod_data.remove(0, 1); + if (mod_data[mod_data.length() - 1] == '}') + mod_data.remove(mod_data.length() - 1, 1); + + QString data_to_send = "{\"to\":\"/topics/" + channel + "\"," + mod_data + "}"; + + QString url = SERVER_ADDRESS; + QUrl uri(url); + QString auth = "key=" + m_auth_key; + QNetworkRequest request(uri); + QString authHeader = QString::fromLatin1("Authorization"); + request.setHeader(QNetworkRequest::ContentTypeHeader, QString::fromLatin1("application/json")); + request.setRawHeader(authHeader.toLocal8Bit(), auth.toLocal8Bit()); + + return sendMessage(POST_MSG, + REQ_SEND_BROADCAST_DATA_TO_CHANNEL, + request, + data_to_send.toUtf8(), + true, + QString()); + +} + +/*! + * \brief FirebaseRestServer::xmlHttpRequestReply + * \param reply + */ +void FirebaseRestServer::xmlHttpRequestReply(QNetworkReply *reply) +{ + getNetworkManager()->disconnect(SIGNAL(finished(QNetworkReply *))); + QString m_msg_uuid = reply->property("uuid").toString(); + int req_id = reply->property("req_id").toInt(); + + if (reply->error()) { + emit xmlHttpRequestError(reply->errorString()); + + } + + // Ok message, lets proceed. + + QByteArray data(reply->readAll()); + + emit xmlHttpRequestReplyData(data); + + reply->deleteLater(); + clearMessage(m_msg_uuid); +} diff --git a/src/cloudmessagingfirebase/qcloudmessagingfirebaserest.h b/src/cloudmessagingfirebase/qcloudmessagingfirebaserest.h new file mode 100644 index 0000000..152bd9e --- /dev/null +++ b/src/cloudmessagingfirebase/qcloudmessagingfirebaserest.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef QCLOUDMESSAGINGFIREBASEREST_H +#define QCLOUDMESSAGINGFIREBASEREST_H + +#include <QtCloudMessaging/QtCloudMessaging> +#include <QtCloudMessaging/qtcloudmessagingglobal.h> +#include <QtCloudMessaging/qcloudmessagingrestapi.h> +#include <QtCloudMessagingFirebase/qcloudmessagingfirebaseclient.h> + +QT_BEGIN_NAMESPACE + +class FirebaseRestServer : public QCloudMessagingRestApi +{ + Q_OBJECT +public: + enum FirebaseRESTRequests { + REQ_NO_REQ, + REQ_GET_DEVICES_BY_CUSTOMER_ID, + REQ_GET_ALL_DEVICES, + REQ_SEND_DATA_TO_DEVICE, + REQ_SEND_BROADCAST_DATA_TO_CHANNEL, + REQ_GET_DEVICE_INFO + }; + Q_ENUM(FirebaseRESTRequests) + + void setAuthKey(const QString &key) + { + m_auth_key = key; + } + + // Response function + void xmlHttpRequestReply(QNetworkReply *reply); + + bool sendToDevice(const QString &token, const QByteArray &data); + bool sendBroadcast(const QString &channel, const QByteArray &data); + +Q_SIGNALS: + void xmlHttpRequestReplyData(const QByteArray &data); + +private: + QString m_auth_key; +}; + +QT_END_NAMESPACE + +#endif // QCLOUDMESSAGINGFIREBASEREST_H diff --git a/src/src.pro b/src/src.pro new file mode 100644 index 0000000..8f68f6c --- /dev/null +++ b/src/src.pro @@ -0,0 +1,8 @@ +TEMPLATE = subdirs +SUBDIRS = cloudmessaging + +embedded-kaltiot { SUBDIRS += cloudmessagingembeddedkaltiot } +firebase { SUBDIRS += cloudmessagingfirebase } + +DISTFILES += \ + ../README.md diff --git a/sync.profile b/sync.profile new file mode 100644 index 0000000..2e9008b --- /dev/null +++ b/sync.profile @@ -0,0 +1,7 @@ +%modules = ( # path to module name map + "QtCloudMessaging" => "$basedir/src/cloudmessaging", + "QtCloudMessagingEmbeddedKaltiot" => "$basedir/src/cloudmessagingembeddedkaltiot", + "QtCloudMessagingFirebase" => "$basedir/src/cloudmessagingfirebase" +); +%moduleheaders = ( # restrict the module headers to those found in relative path +); diff --git a/tests/tests.pro b/tests/tests.pro new file mode 100644 index 0000000..4e68796 --- /dev/null +++ b/tests/tests.pro @@ -0,0 +1,15 @@ +QT += testlib cloudmessaging +QT -= gui + +TARGET = tst_qcloudmessaging +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +DEFINES += QT_DEPRECATED_WARNINGS + +SOURCES += \ + tst_qcloudmessaging.cpp + +DEFINES += SRCDIR=\\\"$$PWD/\\\" diff --git a/tests/tst_qcloudmessaging.cpp b/tests/tst_qcloudmessaging.cpp new file mode 100644 index 0000000..6dd4f1f --- /dev/null +++ b/tests/tst_qcloudmessaging.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCloudMessaging module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QString> +#include <QtTest> + +class QCloudmessaging : public QObject +{ + Q_OBJECT + +public: + QCloudmessaging(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + void testCase1(); +}; + +QCloudmessaging::QCloudmessaging() +{ +} + +void QCloudmessaging::initTestCase() +{ +} + +void QCloudmessaging::cleanupTestCase() +{ +} + +void QCloudmessaging::testCase1() +{ +} + +QTEST_APPLESS_MAIN(QCloudmessaging) + +#include "tst_qcloudmessaging.moc" |