From 5ccc29a2050da9b8524d4dc65c6a10a01061e6f2 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 18 Mar 2020 19:12:31 +0100 Subject: [PATCH 1/2] New Plugin: PushNotifications This plugin allows to send push notifications to nymea:app without the need to go through nymea:cloud. This is useful for users that prefer to not have a cloud account at all and improves privacy and server costs as it cuts out one server hop of the messages. --- debian/control | 16 ++ .../nymea-plugin-pushnotifications.install.in | 1 + nymea-plugins.pro | 1 + pushnotifications/README.md | 31 +++ .../integrationpluginpushnotifications.cpp | 256 ++++++++++++++++++ .../integrationpluginpushnotifications.h | 55 ++++ .../integrationpluginpushnotifications.json | 68 +++++ pushnotifications/pushnotifications.pro | 13 + ...fdcea3b3-8d79-4fbb-8101-1ab45d71cedb-de.ts | 72 +++++ ...ea3b3-8d79-4fbb-8101-1ab45d71cedb-en_US.ts | 72 +++++ 10 files changed, 585 insertions(+) create mode 100644 debian/nymea-plugin-pushnotifications.install.in create mode 100644 pushnotifications/README.md create mode 100644 pushnotifications/integrationpluginpushnotifications.cpp create mode 100644 pushnotifications/integrationpluginpushnotifications.h create mode 100644 pushnotifications/integrationpluginpushnotifications.json create mode 100644 pushnotifications/pushnotifications.pro create mode 100644 pushnotifications/translations/fdcea3b3-8d79-4fbb-8101-1ab45d71cedb-de.ts create mode 100644 pushnotifications/translations/fdcea3b3-8d79-4fbb-8101-1ab45d71cedb-en_US.ts diff --git a/debian/control b/debian/control index 87f28ea3..5a20fe66 100644 --- a/debian/control +++ b/debian/control @@ -638,6 +638,21 @@ Description: nymea.io plugin for Pushbullet This package will install the nymea.io plugin for sending messages via Pushbullet. +Package: nymea-plugin-pushnotifications +Architecture: any +Depends: ${shlibs:Depends}, + ${misc:Depends}, + nymea-plugins-translations, +Description: nymea.io plugin to send Push notifications + The nymea daemon is a plugin based IoT (Internet of Things) server. The + server works like a translator for devices, things and services and + allows them to interact. + With the powerful rule engine you are able to connect any device available + in the system and create individual scenes and behaviors for your environment. + . + This package will install the nymea.io plugin for sending messages via GCM, APNs and UBPorts + + Package: nymea-plugin-solarlog Architecture: any Depends: ${shlibs:Depends}, @@ -1071,6 +1086,7 @@ Depends: nymea-plugin-anel, nymea-plugin-openweathermap, nymea-plugin-philipshue, nymea-plugin-pushbullet, + nymea-plugin-pushnotifications, nymea-plugin-wakeonlan, nymea-plugin-tasmota, nymea-plugin-tplink, diff --git a/debian/nymea-plugin-pushnotifications.install.in b/debian/nymea-plugin-pushnotifications.install.in new file mode 100644 index 00000000..514c1c06 --- /dev/null +++ b/debian/nymea-plugin-pushnotifications.install.in @@ -0,0 +1 @@ +usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginpushnotifications.so diff --git a/nymea-plugins.pro b/nymea-plugins.pro index 5605b2b5..8df8b2d7 100644 --- a/nymea-plugins.pro +++ b/nymea-plugins.pro @@ -42,6 +42,7 @@ PLUGIN_DIRS = \ osdomotics \ philipshue \ pushbullet \ + pushnotifications \ shelly \ solarlog \ systemmonitor \ diff --git a/pushnotifications/README.md b/pushnotifications/README.md new file mode 100644 index 00000000..b5a6d620 --- /dev/null +++ b/pushnotifications/README.md @@ -0,0 +1,31 @@ +# Push Notifications + +This plugin allows to send push notifications to mobile devices. + +## Supported platforms + +* Android (using Firebase Cloud Messaging) +* iOS (using Firebase Cloud Messaging) +* Ubuntu/UBPorts Phone + +## Requirements + +A push notification device token is required during setup. For Android *and* iOS, a Firebase +token is required. Note that native iOS push tokens are not supported as the Apple Push Notification +Service (APNs) does not allow sending messages in such a distributed manner, however, Firebase is available +for iOS too. On Ubuntu, the UBPorts push services are used. + +## More + +During setup, the token, the push service system and a client id needs to be provided. The token is normally +obtained by the operating system. The push service should be selected from GCM, APNs or UBPorts. The client id +must a unique per client and as persistent as possible. + +> Note: Even when using APNs, the token must be obtained using the Firebase SDK as plain APNs does not support sending push notifications from a distributed setup like nymea, but always requires a centralized server on the internet handling all messages. + + +As it is impossible for an end user to obtain this token, a client app should prefill all the parameters +when setting up a push notification thing. Normally, push tokens expire after a while (for instance when +the user clears app data, when the operating system decides to cycle tokens etc). In this case, the client +app should reconfigure its own push notification thing, updating the token with the new one. The client ID +parameter schould be used to find the appropriate thing to reconfigure. diff --git a/pushnotifications/integrationpluginpushnotifications.cpp b/pushnotifications/integrationpluginpushnotifications.cpp new file mode 100644 index 00000000..27779fcb --- /dev/null +++ b/pushnotifications/integrationpluginpushnotifications.cpp @@ -0,0 +1,256 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU Lesser General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; version 3. This project is distributed in the hope that +* it will be useful, but WITHOUT ANY WARRANTY; without even the implied +* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "integrationpluginpushnotifications.h" +#include "plugininfo.h" + +#include "network/networkaccessmanager.h" +#include "nymeasettings.h" + +#include + +// Example payload for Firebase + GCM +//{ +// "android": { +// "notification": { +// "sound": "default" +// }, +// "priority": "high" +// }, +// "data": { +// "body": "text", +// "title": "title" +// }, +// "to": "" +//} + + +// Example payload for Firebase + APNs +//{ +// "apns": { +// "headers": { +// "apns-priority": "10" +// } +// }, +// "notification": { +// "body": "text", +// "sound": "default", +// "title": "title" +// }, +// "to": "" +//} + + +IntegrationPluginPushNotifications::IntegrationPluginPushNotifications(QObject* parent): IntegrationPlugin (parent) +{ +} + +IntegrationPluginPushNotifications::~IntegrationPluginPushNotifications() +{ + +} + +void IntegrationPluginPushNotifications::setupThing(ThingSetupInfo *info) +{ + Thing *thing = info->thing(); + + QString token = thing->paramValue(pushNotificationsThingTokenParamTypeId).toString(); + QString pushService = thing->paramValue(pushNotificationsThingServiceParamTypeId).toString(); + QString clientId = thing->paramValue(pushNotificationsThingClientIdParamTypeId).toString(); + + qCDebug(dcPushNotifications()) << "Setting up push notifications" << thing->name() << "(" << clientId << ") for service" << pushService << "with token" << (token.mid(0, 5) + "******"); + + if (token.isEmpty()) { + //: Error setting up thing + info->finish(Thing::ThingErrorMissingParameter, QT_TR_NOOP("The token must not be empty.")); + return; + } + QStringList availablePushServices = {"FB-GCM", "FB-APNs", "UBPorts"}; + if (!availablePushServices.contains(pushService)) { + //: Error setting up thing + info->finish(Thing::ThingErrorMissingParameter, QT_TR_NOOP("The push service must not be empty.")); + return; + } + + // In case of Firebase, check if we have the required API key + if (pushService.startsWith("FB") && apiKeyStorage()->requestKey("firebase").data("apiKey").isEmpty()) { + //: Error setting up thing + info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Firebase server API key not installed.")); + return; + } + + info->finish(Thing::ThingErrorNoError); +} + +void IntegrationPluginPushNotifications::executeAction(ThingActionInfo *info) +{ + Thing *thing = info->thing(); + Action action = info->action(); + + qCDebug(dcPushNotifications()) << "Executing action" << action.actionTypeId() << "for" << thing->name() << thing->id().toString(); + + QString token = thing->paramValue(pushNotificationsThingTokenParamTypeId).toString(); + QString pushService = thing->paramValue(pushNotificationsThingServiceParamTypeId).toString(); + + QString title = action.param(pushNotificationsNotifyActionTitleParamTypeId).value().toString(); + QString body = action.param(pushNotificationsNotifyActionBodyParamTypeId).value().toString(); + + if (token.isEmpty()) { + return info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Push notifications need to be reconfigured.")); + } + + QNetworkRequest request; + QVariantMap payload; + + if (pushService.startsWith("FB")) { + + ApiKey apiKey = apiKeyStorage()->requestKey("firebase"); + if (apiKey.data("apiKey").isEmpty()) { + info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Firebase server API key not installed.")); + return; + } + + request = QNetworkRequest(QUrl("https://fcm.googleapis.com/fcm/send")); + request.setRawHeader("Authorization", "key=" + apiKey.data("apiKey")); + request.setRawHeader("Content-Type", "application/json"); + + payload.insert("to", token.toUtf8().trimmed()); + + QVariantMap notification; + notification.insert("title", title); + notification.insert("body", body); + + if (pushService == "FB-GCM") { + + QVariantMap soundMap; + soundMap.insert("sound", "default"); + + QVariantMap android; + android.insert("priority", "high"); + android.insert("notification", soundMap); + + payload.insert("android", android); + payload.insert("data", notification); + + } else if (pushService == "FB-APNs") { + + notification.insert("sound", "default"); + + QVariantMap headers; + headers.insert("apns-priority", "10"); + QVariantMap apns; + apns.insert("headers", headers); + + payload.insert("notification", notification); + payload.insert("apns", apns); + } + + + } else if (pushService == "UBPorts") { + request = QNetworkRequest(QUrl("https://push.ubports.com/notify")); + request.setRawHeader("Content-Type", "application/json"); + + QVariantMap card; + card.insert("icon", "notification"); + card.insert("summary", title); + card.insert("body", body); + card.insert("popup", true); + card.insert("persist", true); + + QVariantMap notification; + notification.insert("card", card); + notification.insert("vibrate", true); + notification.insert("sound", true); + + QVariantMap data; + data.insert("notification", notification); + + payload.insert("data", data); + payload.insert("appid", "io.guh.nymeaapp_nymea-app"); + payload.insert("expire_on", QDateTime::currentDateTime().toUTC().addMSecs(1000 * 60 * 10).toString(Qt::ISODate)); + payload.insert("token", token.toUtf8().trimmed()); + } + + qCDebug(dcPushNotifications()) << "Sending notification" << request.url().toString() << qUtf8Printable(QJsonDocument::fromVariant(payload).toJson()); + QNetworkReply *reply = hardwareManager()->networkManager()->post(request, QJsonDocument::fromVariant(payload).toJson(QJsonDocument::Compact)); + connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); + connect(reply, &QNetworkReply::finished, info, [reply, pushService, info, this]{ + if (reply->error() != QNetworkReply::NoError) { + qCWarning(dcPushNotifications()) << "Push message sending failed for" << info->thing()->name() << info->thing()->id() << reply->errorString() << reply->error(); + emit info->finish(Thing::ThingErrorHardwareNotAvailable); + return; + } + + QByteArray data = reply->readAll(); + + QJsonParseError error; + QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); + if (error.error != QJsonParseError::NoError) { + qCWarning(dcPushNotifications()) << "Error reading reply from server for" << info->thing()->name() << info->thing()->id().toString() << error.errorString(); + qCWarning(dcPushNotifications()) << qUtf8Printable(data); + info->finish(Thing::ThingErrorHardwareFailure); + return; + } + + QVariantMap replyMap = jsonDoc.toVariant().toMap(); +// qDebug(dcPushNotifications) << qUtf8Printable(jsonDoc.toJson()); + + if (pushService == "FB-GCM" || pushService == "FB-APNs") { + if (replyMap.value("success").toInt() != 1) { + + // While GCM seems rock solid, APNs fails rather often with Internal Server Error. + // According to Firebase support this is "expected" and one should retry with a exponential back-off timer. + // As we only have 30 secs until the info times out, let's try repeatedly until the info object dies. + // In my tests, so far it succeeded every time on the second attempt. + // https://stackoverflow.com/questions/63382257/firebase-messaging-fails-sporadically-with-internal-error + if (replyMap.value("results").toList().count() > 0 && replyMap.value("results").toList().first().toMap().value("error").toString() == "InternalServerError") { + qCDebug(dcPushNotifications()) << "Sending push message failed. Retrying..."; + executeAction(info); + return; + } + + // On any other error, bail out... + qCWarning(dcPushNotifications()) << "Error sending push notification:" << qUtf8Printable(jsonDoc.toJson()); + info->finish(Thing::ThingErrorHardwareFailure); + return; + } + } else if (pushService == "UBPorts") { + if (!replyMap.value("ok").toBool()) { + qCWarning(dcPushNotifications()) << "Error sending push notification:" << qUtf8Printable(jsonDoc.toJson()); + info->finish(Thing::ThingErrorHardwareFailure); + return; + } + } + + qCDebug(dcPushNotifications()) << "Message sent successfully"; + info->finish(Thing::ThingErrorNoError); + }); +} + diff --git a/pushnotifications/integrationpluginpushnotifications.h b/pushnotifications/integrationpluginpushnotifications.h new file mode 100644 index 00000000..76285663 --- /dev/null +++ b/pushnotifications/integrationpluginpushnotifications.h @@ -0,0 +1,55 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU Lesser General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; version 3. This project is distributed in the hope that +* it will be useful, but WITHOUT ANY WARRANTY; without even the implied +* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef INTEGRATIONPLUGINPUSHNOTIFICATIONS_H +#define INTEGRATIONPLUGINPUSHNOTIFICATIONS_H + +#include "integrations/integrationplugin.h" + +class IntegrationPluginPushNotifications: public IntegrationPlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginpushnotifications.json") + Q_INTERFACES(IntegrationPlugin) + +public: + explicit IntegrationPluginPushNotifications(QObject *parent = nullptr); + ~IntegrationPluginPushNotifications() override; + + void setupThing(ThingSetupInfo *info) override; + void executeAction(ThingActionInfo *info) override; + +private: + QHash m_tokenParamTypeIds; + QByteArray m_firebaseServerToken; +}; + +#endif diff --git a/pushnotifications/integrationpluginpushnotifications.json b/pushnotifications/integrationpluginpushnotifications.json new file mode 100644 index 00000000..ef1b916a --- /dev/null +++ b/pushnotifications/integrationpluginpushnotifications.json @@ -0,0 +1,68 @@ +{ + "displayName": "Push Notifications", + "name": "pushNotifications", + "id": "fdcea3b3-8d79-4fbb-8101-1ab45d71cedb", + "apiKeys": [ "firebase" ], + "vendors": [ + { + "displayName": "nymea GmbH", + "name": "nymea", + "id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6", + "thingClasses": [ + { + "id": "f0dd4c03-0aca-42cc-8f34-9902457b05de", + "name": "pushNotifications", + "displayName": "Push Notifications", + "createMethods": ["user"], + "interfaces": ["notifications"], + "paramTypes": [ + { + "id": "3cb8e30e-2ec5-4b4b-8c8c-03eaf7876839", + "name": "service", + "displayName": "Push service", + "type": "QString", + "allowedValues": ["FB-GCM", "FB-APNs", "UBPorts"] + }, + { + "id": "12ec06b2-44e7-486a-9169-31c684b91c8f", + "name": "token", + "displayName": "access token", + "type": "QString" + }, + { + "id": "d76da367-64e3-4b7d-aa84-c96b3acfb65e", + "name": "clientId", + "displayName": "Client ID", + "type": "QString" + } + ], + "actionTypes": [ + { + "id": "ed9a0196-6c24-4e05-9cbc-c6834de38005", + "name": "notify", + "displayName": "notify", + "paramTypes": [ + { + "id": "3b5e195c-9f96-4f2f-a654-f17ed77c02ee", + "name": "title", + "displayName": "title", + "type": "QString", + "inputType": "TextLine", + "defaultValue": "" + }, + { + "id": "074c4c7c-037f-45ac-ab2f-f7aea3f84bde", + "name": "body", + "displayName": "body", + "type": "QString", + "inputType": "TextArea", + "defaultValue": "" + } + ] + } + ] + } + ] + } + ] +} diff --git a/pushnotifications/pushnotifications.pro b/pushnotifications/pushnotifications.pro new file mode 100644 index 00000000..ac1ed1f7 --- /dev/null +++ b/pushnotifications/pushnotifications.pro @@ -0,0 +1,13 @@ +include(../plugins.pri) + +TARGET = $$qtLibraryTarget(nymea_integrationpluginpushnotifications) + +QT+= network + +SOURCES += \ + integrationpluginpushnotifications.cpp + +HEADERS += \ + integrationpluginpushnotifications.h + + diff --git a/pushnotifications/translations/fdcea3b3-8d79-4fbb-8101-1ab45d71cedb-de.ts b/pushnotifications/translations/fdcea3b3-8d79-4fbb-8101-1ab45d71cedb-de.ts new file mode 100644 index 00000000..405fd946 --- /dev/null +++ b/pushnotifications/translations/fdcea3b3-8d79-4fbb-8101-1ab45d71cedb-de.ts @@ -0,0 +1,72 @@ + + + + + IntegrationPluginPushNotifications + + + The token must not be empty. + Error setting up thing + + + + + The push service must not be empty. + Error setting up thing + + + + + Push notifications need to be reconfigured. + + + + + pushNotifications + + + + Push Notifications + The name of the ThingClass ({f0dd4c03-0aca-42cc-8f34-9902457b05de}) +---------- +The name of the plugin pushNotifications ({fdcea3b3-8d79-4fbb-8101-1ab45d71cedb}) + + + + + Push service + The name of the ParamType (ThingClass: pushNotifications, Type: thing, ID: {3cb8e30e-2ec5-4b4b-8c8c-03eaf7876839}) + + + + + access token + The name of the ParamType (ThingClass: pushNotifications, Type: thing, ID: {12ec06b2-44e7-486a-9169-31c684b91c8f}) + + + + + body + The name of the ParamType (ThingClass: pushNotifications, ActionType: notify, ID: {074c4c7c-037f-45ac-ab2f-f7aea3f84bde}) + + + + + notify + The name of the ActionType ({ed9a0196-6c24-4e05-9cbc-c6834de38005}) of ThingClass pushNotifications + + + + + nymea GmbH + The name of the vendor ({2062d64d-3232-433c-88bc-0d33c0ba2ba6}) + + + + + title + The name of the ParamType (ThingClass: pushNotifications, ActionType: notify, ID: {3b5e195c-9f96-4f2f-a654-f17ed77c02ee}) + + + + diff --git a/pushnotifications/translations/fdcea3b3-8d79-4fbb-8101-1ab45d71cedb-en_US.ts b/pushnotifications/translations/fdcea3b3-8d79-4fbb-8101-1ab45d71cedb-en_US.ts new file mode 100644 index 00000000..405fd946 --- /dev/null +++ b/pushnotifications/translations/fdcea3b3-8d79-4fbb-8101-1ab45d71cedb-en_US.ts @@ -0,0 +1,72 @@ + + + + + IntegrationPluginPushNotifications + + + The token must not be empty. + Error setting up thing + + + + + The push service must not be empty. + Error setting up thing + + + + + Push notifications need to be reconfigured. + + + + + pushNotifications + + + + Push Notifications + The name of the ThingClass ({f0dd4c03-0aca-42cc-8f34-9902457b05de}) +---------- +The name of the plugin pushNotifications ({fdcea3b3-8d79-4fbb-8101-1ab45d71cedb}) + + + + + Push service + The name of the ParamType (ThingClass: pushNotifications, Type: thing, ID: {3cb8e30e-2ec5-4b4b-8c8c-03eaf7876839}) + + + + + access token + The name of the ParamType (ThingClass: pushNotifications, Type: thing, ID: {12ec06b2-44e7-486a-9169-31c684b91c8f}) + + + + + body + The name of the ParamType (ThingClass: pushNotifications, ActionType: notify, ID: {074c4c7c-037f-45ac-ab2f-f7aea3f84bde}) + + + + + notify + The name of the ActionType ({ed9a0196-6c24-4e05-9cbc-c6834de38005}) of ThingClass pushNotifications + + + + + nymea GmbH + The name of the vendor ({2062d64d-3232-433c-88bc-0d33c0ba2ba6}) + + + + + title + The name of the ParamType (ThingClass: pushNotifications, ActionType: notify, ID: {3b5e195c-9f96-4f2f-a654-f17ed77c02ee}) + + + + From 38fbd0266d171ae007ba20be8ddee2f8964a9269 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sat, 9 Jan 2021 00:56:16 +0100 Subject: [PATCH 2/2] Allow configuring the plugin with a dummy backend --- pushnotifications/README.md | 2 +- .../integrationpluginpushnotifications.cpp | 19 ++++++++++++------- .../integrationpluginpushnotifications.json | 2 +- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/pushnotifications/README.md b/pushnotifications/README.md index b5a6d620..c0f105a9 100644 --- a/pushnotifications/README.md +++ b/pushnotifications/README.md @@ -18,7 +18,7 @@ for iOS too. On Ubuntu, the UBPorts push services are used. ## More During setup, the token, the push service system and a client id needs to be provided. The token is normally -obtained by the operating system. The push service should be selected from GCM, APNs or UBPorts. The client id +obtained by the operating system. The push service should be selected from FB-GCM, FB-APNs or UBPorts. The client id must a unique per client and as persistent as possible. > Note: Even when using APNs, the token must be obtained using the Firebase SDK as plain APNs does not support sending push notifications from a distributed setup like nymea, but always requires a centralized server on the internet handling all messages. diff --git a/pushnotifications/integrationpluginpushnotifications.cpp b/pushnotifications/integrationpluginpushnotifications.cpp index 27779fcb..74b7e7e6 100644 --- a/pushnotifications/integrationpluginpushnotifications.cpp +++ b/pushnotifications/integrationpluginpushnotifications.cpp @@ -87,18 +87,19 @@ void IntegrationPluginPushNotifications::setupThing(ThingSetupInfo *info) qCDebug(dcPushNotifications()) << "Setting up push notifications" << thing->name() << "(" << clientId << ") for service" << pushService << "with token" << (token.mid(0, 5) + "******"); - if (token.isEmpty()) { - //: Error setting up thing - info->finish(Thing::ThingErrorMissingParameter, QT_TR_NOOP("The token must not be empty.")); - return; - } - QStringList availablePushServices = {"FB-GCM", "FB-APNs", "UBPorts"}; + QStringList availablePushServices = {"FB-GCM", "FB-APNs", "UBPorts", "None"}; if (!availablePushServices.contains(pushService)) { //: Error setting up thing info->finish(Thing::ThingErrorMissingParameter, QT_TR_NOOP("The push service must not be empty.")); return; } + if (pushService != "None" && token.isEmpty()) { + //: Error setting up thing + info->finish(Thing::ThingErrorMissingParameter, QT_TR_NOOP("The token must not be empty.")); + return; + } + // In case of Firebase, check if we have the required API key if (pushService.startsWith("FB") && apiKeyStorage()->requestKey("firebase").data("apiKey").isEmpty()) { //: Error setting up thing @@ -122,7 +123,7 @@ void IntegrationPluginPushNotifications::executeAction(ThingActionInfo *info) QString title = action.param(pushNotificationsNotifyActionTitleParamTypeId).value().toString(); QString body = action.param(pushNotificationsNotifyActionBodyParamTypeId).value().toString(); - if (token.isEmpty()) { + if (pushService != "None" && token.isEmpty()) { return info->finish(Thing::ThingErrorAuthenticationFailure, QT_TR_NOOP("Push notifications need to be reconfigured.")); } @@ -196,6 +197,10 @@ void IntegrationPluginPushNotifications::executeAction(ThingActionInfo *info) payload.insert("appid", "io.guh.nymeaapp_nymea-app"); payload.insert("expire_on", QDateTime::currentDateTime().toUTC().addMSecs(1000 * 60 * 10).toString(Qt::ISODate)); payload.insert("token", token.toUtf8().trimmed()); + } else if (pushService == "None") { + // Nothing to do here... It's the clients responsibility to fetch it from nymea + info->finish(Thing::ThingErrorNoError); + return; } qCDebug(dcPushNotifications()) << "Sending notification" << request.url().toString() << qUtf8Printable(QJsonDocument::fromVariant(payload).toJson()); diff --git a/pushnotifications/integrationpluginpushnotifications.json b/pushnotifications/integrationpluginpushnotifications.json index ef1b916a..382b613b 100644 --- a/pushnotifications/integrationpluginpushnotifications.json +++ b/pushnotifications/integrationpluginpushnotifications.json @@ -21,7 +21,7 @@ "name": "service", "displayName": "Push service", "type": "QString", - "allowedValues": ["FB-GCM", "FB-APNs", "UBPorts"] + "allowedValues": ["FB-GCM", "FB-APNs", "UBPorts", "None"] }, { "id": "12ec06b2-44e7-486a-9169-31c684b91c8f",