diff --git a/QtZeroConf b/QtZeroConf
index 1e36e430..d3e03568 160000
--- a/QtZeroConf
+++ b/QtZeroConf
@@ -1 +1 @@
-Subproject commit 1e36e430e98ecec6e15ab06f56467567f22f9e8a
+Subproject commit d3e03568a9f20ccd4f98f6a183d411a441f49482
diff --git a/clickable.json b/clickable.json
index 78f3ffc8..882d82db 100644
--- a/clickable.json
+++ b/clickable.json
@@ -1,11 +1,13 @@
{
"template": "qmake",
"kill": "nymea-app",
- "build_args": "CONFIG+=click CONFIG+=ubuntu",
+ "build_args": "CONFIG+=ubports",
"dependencies_target": [
"libavahi-client-dev",
"libavahi-common-dev",
"libqt5charts5-dev",
- "qml-module-qtcharts"
+ "qml-module-qtcharts",
+ "libconnectivity-qt1-dev",
+ "libunity-api-dev"
]
}
diff --git a/libnymea-app-core/connection/awsclient.cpp b/libnymea-app-core/connection/awsclient.cpp
index 2892f3b1..48eedd15 100644
--- a/libnymea-app-core/connection/awsclient.cpp
+++ b/libnymea-app-core/connection/awsclient.cpp
@@ -56,6 +56,8 @@ AWSClient::AWSClient(QObject *parent) : QObject(parent),
QString pushSystem = "GCM";
#elif defined Q_OS_IOS
QString pushSystem = "APNS";
+#elif UBPORTS
+ QString pushSystem = "UBPORTS";
#else
QString pushSystem = "";
#endif
@@ -645,7 +647,7 @@ void AWSClient::registerPushNotificationEndpoint(const QString ®istrationId,
QJsonDocument jsonDoc = QJsonDocument::fromVariant(payload);
- qDebug() << "Registering push notification endpoint";
+ qDebug() << "Registering push notification endpoint" << qUtf8Printable(QJsonDocument::fromVariant(payload).toJson());
// qDebug() << "POST" << url.toString();
// qDebug() << "HEADERS:";
// foreach (const QByteArray &hdr, request.rawHeaderList()) {
diff --git a/libnymea-app-core/devicemanager.cpp b/libnymea-app-core/devicemanager.cpp
index 325b099b..01f67de4 100644
--- a/libnymea-app-core/devicemanager.cpp
+++ b/libnymea-app-core/devicemanager.cpp
@@ -213,7 +213,7 @@ void DeviceManager::getVendorsResponse(const QVariantMap ¶ms)
void DeviceManager::getSupportedDevicesResponse(const QVariantMap ¶ms)
{
- qDebug() << "DeviceClass received:" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
+// qDebug() << "DeviceClass received:" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
if (params.value("params").toMap().keys().contains("deviceClasses")) {
QVariantList deviceClassList = params.value("params").toMap().value("deviceClasses").toList();
foreach (QVariant deviceClassVariant, deviceClassList) {
diff --git a/libnymea-app-core/libnymea-app-core.pro b/libnymea-app-core/libnymea-app-core.pro
index 309dcbe8..beccd059 100644
--- a/libnymea-app-core/libnymea-app-core.pro
+++ b/libnymea-app-core/libnymea-app-core.pro
@@ -146,3 +146,8 @@ HEADERS += \
configuration/mqttpolicies.h \
models/devicemodel.h \
system/systemcontroller.h
+
+
+ubports: {
+ DEFINES += UBPORTS
+}
diff --git a/nymea-app.pro b/nymea-app.pro
index c9c5675e..1c9a1a0f 100644
--- a/nymea-app.pro
+++ b/nymea-app.pro
@@ -85,9 +85,17 @@ desktopfile.path = /usr/share/applications/
INSTALLS += desktopfile
}
-click: {
-ubuntu_files.path += /
-ubuntu_files.files += manifest.json nymea-app.apparmor nymea-app.desktop packaging/android/appicon.svg
+ubports: {
+ubuntu_files.path = /
+ubuntu_files.files += \
+ packaging/ubuntu/click/manifest.json \
+ packaging/ubuntu/click/nymea-app.apparmor \
+ packaging/ubuntu/click/nymea-app.desktop \
+ packaging/ubuntu/click/appicon.svg \
+ packaging/ubuntu/click/push.json \
+ packaging/ubuntu/click/push-apparmor.json \
+ packaging/ubuntu/click/pushexec
+
INSTALLS += ubuntu_files
}
diff --git a/nymea-app/nymea-app.pro b/nymea-app/nymea-app.pro
index fe9b360f..ed2116d8 100644
--- a/nymea-app/nymea-app.pro
+++ b/nymea-app/nymea-app.pro
@@ -129,6 +129,17 @@ ios: {
QMAKE_MAC_XCODE_SETTINGS += IOS_ENTITLEMENTS
}
+ubports: {
+ DEFINES += UBPORTS
+
+ CONFIG += link_pkgconfig
+ PKGCONFIG += connectivity-qt1
+
+ HEADERS += platformintegration/ubports/pushclient.h
+
+ SOURCES += platformintegration/ubports/pushclient.cpp
+}
+
BR=$$BRANDING
!equals(BR, "") {
DEFINES += BRANDING=\\\"$${BR}\\\"
diff --git a/nymea-app/platformintegration/ubports/pushclient.cpp b/nymea-app/platformintegration/ubports/pushclient.cpp
new file mode 100644
index 00000000..9ea8d44d
--- /dev/null
+++ b/nymea-app/platformintegration/ubports/pushclient.cpp
@@ -0,0 +1,208 @@
+/*
+Copyright 2014 Canonical Ltd.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License, version 3
+as published by the Free Software Foundation.
+
+This program 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 program. If not, see
+.
+*/
+
+#include "pushclient.h"
+#include
+#include
+#include
+#include
+#include
+
+#define PUSH_SERVICE "com.ubuntu.PushNotifications"
+#define POSTAL_SERVICE "com.ubuntu.Postal"
+#define PUSH_PATH "/com/ubuntu/PushNotifications"
+#define POSTAL_PATH "/com/ubuntu/Postal"
+#define PUSH_IFACE "com.ubuntu.PushNotifications"
+#define POSTAL_IFACE "com.ubuntu.Postal"
+
+PushClient::PushClient(QObject *parent) :
+ QObject(parent),
+ ns(new connectivityqt::Connectivity(QDBusConnection::sessionBus(), this))
+{
+}
+
+void PushClient::setAppId(const QString &appId) {
+ if (appId == this->appId || appId.isEmpty())
+ return;
+
+ this->appId = appId;
+ emit appIdChanged(appId);
+
+ if (ns->online()) {
+ registerApp();
+ } else {
+ disconnect(ns.data(), 0, this, 0);
+ connect(ns.data(), &connectivityqt::Connectivity::onlineUpdated, this, &PushClient::connectionStatusChanged);
+ }
+}
+
+void PushClient::connectionStatusChanged(bool status)
+{
+ if (status) {
+ disconnect(ns.data(), 0, this, 0);
+ registerApp();
+ }
+}
+
+void PushClient::registerApp()
+{
+ if (appId.isEmpty())
+ return;
+
+ pkgname = appId.split("_").at(0);
+ pkgname = pkgname.replace(".","_2e").replace("-","_2d");
+
+ QString register_path(PUSH_PATH);
+ register_path += "/" + pkgname;
+
+ QDBusConnection bus = QDBusConnection::sessionBus();
+
+ // Register to the push client
+ QDBusMessage message = QDBusMessage::createMethodCall(PUSH_SERVICE, register_path , PUSH_IFACE, "Register");
+ message << appId;
+ QDBusPendingCall pcall = bus.asyncCall(message);
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, &PushClient::registerFinished);
+
+ // Connect to the notification signal
+ QString postal_path(POSTAL_PATH);
+ postal_path += "/" + pkgname;
+ bus.connect(POSTAL_SERVICE, postal_path, POSTAL_IFACE, "Post", "s", this, SLOT(notified(QString)));
+}
+
+void PushClient::registerFinished(QDBusPendingCallWatcher *watcher) {
+ QDBusPendingReply reply = *watcher;
+ if (reply.isError()) {
+ status = reply.error().message();
+ emit statusChanged(status);
+ // This has to be delayed because the error signal is not connected yet
+ QTimer::singleShot(200, this, &PushClient::emitError);
+ }
+ else {
+ this->token = reply.value();
+ // Do an initial fetch
+ QTimer::singleShot(200, this, &PushClient::getNotifications);
+ emit tokenChanged(this->token);
+ }
+ watcher->deleteLater();
+}
+
+QString PushClient::getAppId() {
+ return appId;
+}
+
+QString PushClient::getToken() {
+ return token;
+}
+
+void PushClient::emitError()
+{
+ emit error(status);
+}
+
+void PushClient::notified(const QString &)
+{
+ this->getNotifications();
+}
+
+void PushClient::getNotifications() {
+ QDBusConnection bus = QDBusConnection::sessionBus();
+ QString path(POSTAL_PATH);
+ path += "/" + pkgname;
+ QDBusMessage message = QDBusMessage::createMethodCall(POSTAL_SERVICE, path, POSTAL_IFACE, "PopAll");
+ message << this->appId;
+ QDBusPendingCall pcall = bus.asyncCall(message);
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,this, &PushClient::popAllFinished);
+}
+
+void PushClient::popAllFinished(QDBusPendingCallWatcher *watcher) {
+ QDBusPendingReply reply = *watcher;
+ if (reply.isError()) {
+ emit error(reply.error().message());
+ }
+ else {
+ emit notificationsChanged(reply.value());
+ }
+ watcher->deleteLater();
+}
+
+QStringList PushClient::getPersistent() {
+ // FIXME: this is blocking, but making it async would change the API
+ QDBusConnection bus = QDBusConnection::sessionBus();
+ QString path(POSTAL_PATH);
+ path += "/" + pkgname;
+ QDBusMessage message = QDBusMessage::createMethodCall(POSTAL_SERVICE, path, POSTAL_IFACE, "ListPersistent");
+ message << this->appId;
+ QDBusMessage reply = bus.call(message);
+ if (reply.type() == QDBusMessage::ErrorMessage) {
+ emit error(reply.errorMessage());
+ }
+ return reply.arguments()[0].toStringList();
+}
+
+void PushClient::clearPersistent(const QStringList &tags) {
+ QDBusConnection bus = QDBusConnection::sessionBus();
+ QString path(POSTAL_PATH);
+ path += "/" + pkgname;
+ QDBusMessage message = QDBusMessage::createMethodCall(POSTAL_SERVICE, path, POSTAL_IFACE, "ClearPersistent");
+ message << this->appId;
+ for (int i = 0; i < tags.size(); ++i) {
+ message << tags.at(i);
+ }
+ QDBusPendingCall pcall = bus.asyncCall(message);
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, &PushClient::clearPersistentFinished);
+}
+
+void PushClient::clearPersistentFinished(QDBusPendingCallWatcher *watcher) {
+ QDBusPendingReply reply = *watcher;
+
+ if (reply.isError()) {
+ emit error(reply.error().message());
+ } else {
+ // FIXME: this is blocking
+ emit persistentChanged(getPersistent());
+ }
+}
+
+void PushClient::setCount(int count) {
+ QDBusConnection bus = QDBusConnection::sessionBus();
+ QString path(POSTAL_PATH);
+ bool visible = count != 0;
+ counter = count;
+ path += "/" + pkgname;
+ QDBusMessage message = QDBusMessage::createMethodCall(POSTAL_SERVICE, path, POSTAL_IFACE, "SetCounter");
+ message << this->appId << count << visible;
+ QDBusPendingCall pcall = bus.asyncCall(message);
+ QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pcall, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished, this, &PushClient::setCounterFinished);
+}
+
+void PushClient::setCounterFinished(QDBusPendingCallWatcher *watcher) {
+ QDBusPendingReply reply = *watcher;
+ if (reply.isError()) {
+ emit error(reply.error().message());
+ }
+ else {
+ emit countChanged(counter);
+ }
+}
+
+int PushClient::getCount() {
+ return counter;
+}
diff --git a/nymea-app/platformintegration/ubports/pushclient.h b/nymea-app/platformintegration/ubports/pushclient.h
new file mode 100644
index 00000000..044a6502
--- /dev/null
+++ b/nymea-app/platformintegration/ubports/pushclient.h
@@ -0,0 +1,82 @@
+/*
+Copyright 2014 Canonical Ltd.
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License, version 3
+as published by the Free Software Foundation.
+
+This program 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 program. If not, see
+.
+*/
+
+#ifndef PUSHCLIENT_H
+#define PUSHCLIENT_H
+
+#include
+#include
+#include
+#include
+
+class QDBusPendingCallWatcher;
+
+class PushClient : public QObject
+{
+ Q_OBJECT
+public:
+ explicit PushClient(QObject *parent = 0);
+ void setAppId(const QString &appid);
+ QString getStatus() {return this->status;}
+ QString getAppId();
+ QString getToken();
+ QStringList getPersistent();
+ void setCount(int count);
+ int getCount();
+
+ Q_PROPERTY(QString appId WRITE setAppId READ getAppId NOTIFY appIdChanged)
+ Q_PROPERTY(QString token READ getToken NOTIFY tokenChanged)
+ Q_PROPERTY(QStringList notifications MEMBER notifications NOTIFY notificationsChanged)
+ Q_PROPERTY(QString status READ getStatus NOTIFY statusChanged)
+ Q_PROPERTY(QStringList persistent READ getPersistent NOTIFY persistentChanged)
+ Q_PROPERTY(int count READ getCount WRITE setCount NOTIFY countChanged)
+
+signals:
+ void countChanged(int count);
+ void notificationsChanged(const QStringList ¬ifications);
+ void persistentChanged(const QStringList &tags);
+ void appIdChanged(const QString &appId);
+ void error(const QString &error);
+ void tokenChanged(const QString &token);
+ void statusChanged(const QString &status);
+
+public slots:
+ void getNotifications();
+ void notified(const QString &appId);
+ void emitError();
+ void clearPersistent(const QStringList &tags);
+
+private slots:
+ void registerFinished(QDBusPendingCallWatcher *watcher);
+ void popAllFinished(QDBusPendingCallWatcher *watcher);
+ void setCounterFinished(QDBusPendingCallWatcher *watcher);
+ void clearPersistentFinished(QDBusPendingCallWatcher *watcher);
+ void connectionStatusChanged(bool status);
+
+private:
+ void registerApp();
+
+ QScopedPointer ns;
+ QString appId;
+ QString pkgname;
+ QString token;
+ QString status;
+ QStringList notifications;
+ int counter;
+};
+
+#endif // PUSHCLIENT_H
diff --git a/nymea-app/pushnotifications.cpp b/nymea-app/pushnotifications.cpp
index c02384c4..6151d69b 100644
--- a/nymea-app/pushnotifications.cpp
+++ b/nymea-app/pushnotifications.cpp
@@ -6,13 +6,21 @@
#include
#include
#include
-#endif
-
static PushNotifications *m_client_pointer;
+#endif
PushNotifications::PushNotifications(QObject *parent) : QObject(parent)
{
connectClient();
+
+#ifdef UBPORTS
+ m_pushClient = new PushClient(this);
+ m_pushClient->setAppId("io.guh.nymeaapp_nymea-app");
+ connect(m_pushClient, &PushClient::tokenChanged, this, [this](const QString &token) {
+ m_token = token;
+ emit tokenChanged();
+ });
+#endif
}
QObject *PushNotifications::pushNotificationsProvider(QQmlEngine *engine, QJSEngine *scriptEngine)
diff --git a/nymea-app/pushnotifications.h b/nymea-app/pushnotifications.h
index b32996e7..b82a2eab 100644
--- a/nymea-app/pushnotifications.h
+++ b/nymea-app/pushnotifications.h
@@ -8,6 +8,11 @@
#include "firebase/app.h"
#include "firebase/messaging.h"
#include "firebase/util.h"
+
+#elif UBPORTS
+
+#include "platformintegration/ubports/pushclient.h"
+
#endif
#ifdef Q_OS_ANDROID
@@ -44,6 +49,11 @@ protected:
private:
::firebase::App *m_firebaseApp = nullptr;
::firebase::ModuleInitializer m_firebase_initializer;
+
+#elif UBPORTS
+
+ PushClient *m_pushClient = nullptr;
+
#endif
private:
diff --git a/packaging/ubuntu/click/appicon.svg b/packaging/ubuntu/click/appicon.svg
new file mode 100644
index 00000000..7f1ddd65
--- /dev/null
+++ b/packaging/ubuntu/click/appicon.svg
@@ -0,0 +1,610 @@
+
+
+
+
diff --git a/manifest.json b/packaging/ubuntu/click/manifest.json
similarity index 75%
rename from manifest.json
rename to packaging/ubuntu/click/manifest.json
index ab7716eb..b032d75c 100644
--- a/manifest.json
+++ b/packaging/ubuntu/click/manifest.json
@@ -7,9 +7,13 @@
"nymea-app": {
"apparmor": "nymea-app.apparmor",
"desktop": "nymea-app.desktop"
+ },
+ "push": {
+ "apparmor": "push-apparmor.json",
+ "push-helper": "push.json"
}
},
- "version": "developer-build",
+ "version": "0",
"maintainer": "Michael Zanetti ",
- "framework" : "ubuntu-sdk-15.04.5"
+ "framework" : "ubuntu-sdk-16.04"
}
diff --git a/nymea-app.apparmor b/packaging/ubuntu/click/nymea-app.apparmor
similarity index 100%
rename from nymea-app.apparmor
rename to packaging/ubuntu/click/nymea-app.apparmor
diff --git a/nymea-app.desktop b/packaging/ubuntu/click/nymea-app.desktop
similarity index 100%
rename from nymea-app.desktop
rename to packaging/ubuntu/click/nymea-app.desktop
diff --git a/packaging/ubuntu/click/push-apparmor.json b/packaging/ubuntu/click/push-apparmor.json
new file mode 100644
index 00000000..af147848
--- /dev/null
+++ b/packaging/ubuntu/click/push-apparmor.json
@@ -0,0 +1,7 @@
+{
+ "template": "ubuntu-push-helper",
+ "policy_groups": [
+ "push-notification-client"
+ ],
+ "policy_version": 16.04
+}
diff --git a/packaging/ubuntu/click/push.json b/packaging/ubuntu/click/push.json
new file mode 100644
index 00000000..d9a9e170
--- /dev/null
+++ b/packaging/ubuntu/click/push.json
@@ -0,0 +1,4 @@
+{
+ "exec": "pushexec"
+}
+
diff --git a/packaging/ubuntu/click/pushexec b/packaging/ubuntu/click/pushexec
new file mode 100755
index 00000000..5de224cf
--- /dev/null
+++ b/packaging/ubuntu/click/pushexec
@@ -0,0 +1,19 @@
+#!/usr/bin/python3
+
+import os
+import sys
+import json
+
+f1, f2 = sys.argv[1:3]
+
+payloadJson = json.load(open(f1))
+
+dir_path = os.path.dirname(os.path.realpath(__file__))
+payloadJson["notification"]["card"]["icon"] = dir_path + "/appicon.svg"
+
+payloadJson["notification"]["card"]["actions"] = ["appid://io.guh.nymeaapp/nymea-app/current-user-version"]
+#payloadJson["notification"]["emblem-counter"] = {"count": 1, "visible": True }
+
+print(payloadJson)
+open(f2, "w").write(json.dumps(payloadJson) + "\n")
+