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.master
parent
6e781113e5
commit
5ccc29a205
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginpushnotifications.so
|
||||
|
|
@ -42,6 +42,7 @@ PLUGIN_DIRS = \
|
|||
osdomotics \
|
||||
philipshue \
|
||||
pushbullet \
|
||||
pushnotifications \
|
||||
shelly \
|
||||
solarlog \
|
||||
systemmonitor \
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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 <QJsonDocument>
|
||||
|
||||
// Example payload for Firebase + GCM
|
||||
//{
|
||||
// "android": {
|
||||
// "notification": {
|
||||
// "sound": "default"
|
||||
// },
|
||||
// "priority": "high"
|
||||
// },
|
||||
// "data": {
|
||||
// "body": "text",
|
||||
// "title": "title"
|
||||
// },
|
||||
// "to": "<client token>"
|
||||
//}
|
||||
|
||||
|
||||
// Example payload for Firebase + APNs
|
||||
//{
|
||||
// "apns": {
|
||||
// "headers": {
|
||||
// "apns-priority": "10"
|
||||
// }
|
||||
// },
|
||||
// "notification": {
|
||||
// "body": "text",
|
||||
// "sound": "default",
|
||||
// "title": "title"
|
||||
// },
|
||||
// "to": "<client token>"
|
||||
//}
|
||||
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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<ThingClassId, ParamTypeId> m_tokenParamTypeIds;
|
||||
QByteArray m_firebaseServerToken;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -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": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
include(../plugins.pri)
|
||||
|
||||
TARGET = $$qtLibraryTarget(nymea_integrationpluginpushnotifications)
|
||||
|
||||
QT+= network
|
||||
|
||||
SOURCES += \
|
||||
integrationpluginpushnotifications.cpp
|
||||
|
||||
HEADERS += \
|
||||
integrationpluginpushnotifications.h
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
<context>
|
||||
<name>IntegrationPluginPushNotifications</name>
|
||||
<message>
|
||||
<location filename="../integrationpluginpushnotifications.cpp" line="71"/>
|
||||
<source>The token must not be empty.</source>
|
||||
<extracomment>Error setting up thing</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../integrationpluginpushnotifications.cpp" line="76"/>
|
||||
<source>The push service must not be empty.</source>
|
||||
<extracomment>Error setting up thing</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../integrationpluginpushnotifications.cpp" line="96"/>
|
||||
<source>Push notifications need to be reconfigured.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>pushNotifications</name>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="28"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="31"/>
|
||||
<source>Push Notifications</source>
|
||||
<extracomment>The name of the ThingClass ({f0dd4c03-0aca-42cc-8f34-9902457b05de})
|
||||
----------
|
||||
The name of the plugin pushNotifications ({fdcea3b3-8d79-4fbb-8101-1ab45d71cedb})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="34"/>
|
||||
<source>Push service</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: pushNotifications, Type: thing, ID: {3cb8e30e-2ec5-4b4b-8c8c-03eaf7876839})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="37"/>
|
||||
<source>access token</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: pushNotifications, Type: thing, ID: {12ec06b2-44e7-486a-9169-31c684b91c8f})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="40"/>
|
||||
<source>body</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: pushNotifications, ActionType: notify, ID: {074c4c7c-037f-45ac-ab2f-f7aea3f84bde})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="43"/>
|
||||
<source>notify</source>
|
||||
<extracomment>The name of the ActionType ({ed9a0196-6c24-4e05-9cbc-c6834de38005}) of ThingClass pushNotifications</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="46"/>
|
||||
<source>nymea GmbH</source>
|
||||
<extracomment>The name of the vendor ({2062d64d-3232-433c-88bc-0d33c0ba2ba6})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="49"/>
|
||||
<source>title</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: pushNotifications, ActionType: notify, ID: {3b5e195c-9f96-4f2f-a654-f17ed77c02ee})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE TS>
|
||||
<TS version="2.1">
|
||||
<context>
|
||||
<name>IntegrationPluginPushNotifications</name>
|
||||
<message>
|
||||
<location filename="../integrationpluginpushnotifications.cpp" line="71"/>
|
||||
<source>The token must not be empty.</source>
|
||||
<extracomment>Error setting up thing</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../integrationpluginpushnotifications.cpp" line="76"/>
|
||||
<source>The push service must not be empty.</source>
|
||||
<extracomment>Error setting up thing</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../integrationpluginpushnotifications.cpp" line="96"/>
|
||||
<source>Push notifications need to be reconfigured.</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>pushNotifications</name>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="28"/>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="31"/>
|
||||
<source>Push Notifications</source>
|
||||
<extracomment>The name of the ThingClass ({f0dd4c03-0aca-42cc-8f34-9902457b05de})
|
||||
----------
|
||||
The name of the plugin pushNotifications ({fdcea3b3-8d79-4fbb-8101-1ab45d71cedb})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="34"/>
|
||||
<source>Push service</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: pushNotifications, Type: thing, ID: {3cb8e30e-2ec5-4b4b-8c8c-03eaf7876839})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="37"/>
|
||||
<source>access token</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: pushNotifications, Type: thing, ID: {12ec06b2-44e7-486a-9169-31c684b91c8f})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="40"/>
|
||||
<source>body</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: pushNotifications, ActionType: notify, ID: {074c4c7c-037f-45ac-ab2f-f7aea3f84bde})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="43"/>
|
||||
<source>notify</source>
|
||||
<extracomment>The name of the ActionType ({ed9a0196-6c24-4e05-9cbc-c6834de38005}) of ThingClass pushNotifications</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="46"/>
|
||||
<source>nymea GmbH</source>
|
||||
<extracomment>The name of the vendor ({2062d64d-3232-433c-88bc-0d33c0ba2ba6})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../../../build-nymea-plugins-Desktop-Debug/pushnotifications/plugininfo.h" line="49"/>
|
||||
<source>title</source>
|
||||
<extracomment>The name of the ParamType (ThingClass: pushNotifications, ActionType: notify, ID: {3b5e195c-9f96-4f2f-a654-f17ed77c02ee})</extracomment>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
</TS>
|
||||
Loading…
Reference in New Issue