summaryrefslogtreecommitdiffstats
path: root/sample
diff options
context:
space:
mode:
authorDmitry Yudenich <dmitry.yudenich@orioninc.com>2020-07-10 14:40:15 +0300
committerDmitry Yudenich <dmitry.yudenich@orioninc.com>2020-07-16 16:39:27 +0300
commitaee2ff16cc87a939e68aa2900e23d6705dda5408 (patch)
tree2ba8cfe056758e60f5e003e45b4352b6f759f2cf /sample
parentd42a34b42837129dc98cd9ae115711da63eb6d62 (diff)
Add client proxy for cloudproxy servicejellyfish_9.99.4jellyfish/9.99.49.99.4
Library with client proxy which hides communication with cloud proxy service has been added. It allows users to integrate cloudproxy service in their applications faster. Simple test applications have been added to demonstrate how to use libcloudproxy library. Bug-AGL: SPEC-3472 Signed-off-by: Dmitry Yudenich <dmitry.yudenich@orioninc.com> Change-Id: I84ab5e61ce09326e3dc49c927d402e6ec12ea1b0
Diffstat (limited to 'sample')
-rwxr-xr-xsample/README.md98
-rwxr-xr-xsample/telemetry-cloud-app/app/TelemetryWorker.cpp116
-rwxr-xr-xsample/telemetry-cloud-app/app/TelemetryWorker.h48
-rwxr-xr-xsample/telemetry-cloud-app/app/app.pri3
-rwxr-xr-xsample/telemetry-cloud-app/app/app.pro32
-rwxr-xr-xsample/telemetry-cloud-app/app/images/AGL_HMI_Blue_Background_NoCar-01.pngbin0 -> 698586 bytes
-rwxr-xr-xsample/telemetry-cloud-app/app/images/images.qrc5
-rwxr-xr-xsample/telemetry-cloud-app/app/main.cpp92
-rwxr-xr-xsample/telemetry-cloud-app/app/mainwindow.cpp100
-rwxr-xr-xsample/telemetry-cloud-app/app/mainwindow.h52
-rwxr-xr-xsample/telemetry-cloud-app/app/ui_mainwindow.h86
-rwxr-xr-xsample/telemetry-cloud-app/autobuild/agl/autobuild110
-rwxr-xr-xsample/telemetry-cloud-app/autobuild/linux/autobuild110
-rwxr-xr-xsample/telemetry-cloud-app/package/config.xml17
-rwxr-xr-xsample/telemetry-cloud-app/package/icon.svg266
-rwxr-xr-xsample/telemetry-cloud-app/package/package.pro28
-rwxr-xr-xsample/telemetry-cloud-app/telemetrycloudapp.pro3
-rwxr-xr-xsample/test-cloud-app/app/app.pri3
-rwxr-xr-xsample/test-cloud-app/app/app.pro31
-rwxr-xr-xsample/test-cloud-app/app/images/AGL_HMI_Blue_Background_NoCar-01.pngbin0 -> 698586 bytes
-rwxr-xr-xsample/test-cloud-app/app/images/images.qrc5
-rwxr-xr-xsample/test-cloud-app/app/main.cpp119
-rwxr-xr-xsample/test-cloud-app/app/main.cpp.save148
-rwxr-xr-xsample/test-cloud-app/app/mainwindow.cpp83
-rwxr-xr-xsample/test-cloud-app/app/mainwindow.h55
-rwxr-xr-xsample/test-cloud-app/app/ui_mainwindow.h94
-rwxr-xr-xsample/test-cloud-app/autobuild/agl/autobuild110
-rwxr-xr-xsample/test-cloud-app/autobuild/linux/autobuild110
-rwxr-xr-xsample/test-cloud-app/package/config.xml17
-rwxr-xr-xsample/test-cloud-app/package/icon.svg266
-rwxr-xr-xsample/test-cloud-app/package/package.pro28
-rwxr-xr-xsample/test-cloud-app/testcloudapp.pro3
32 files changed, 2238 insertions, 0 deletions
diff --git a/sample/README.md b/sample/README.md
new file mode 100755
index 0000000..8edaddd
--- /dev/null
+++ b/sample/README.md
@@ -0,0 +1,98 @@
+# Test cloud applications #
+
+## Description
+
+The test-cloud-app and telemetry-cloud-app are examples of an agl-cloudproxy-service client.
+They are used to demonstrate the possibilities of the cloudproxy service.
+
+## Applications
+
+* test-cloud-app: Simple application demonstrating the following possibilities:
+ * Sending the messages to cloud over cloud proxy server
+ * Receiving confirmations from cloud on the sent messages
+ * Receiving messages from cloud
+
+
+* telemetry-cloud-app: Application which sends the GPS coordinates to the cloud
+ * Sending of the messages with telemetry to the cloud
+ * Receiving of the messages from the cloud
+
+Applications use CloudProxy client as high level interface for the messages sending and receiving
+
+## CloudProxy client
+
+CloudProxy client hides the communication with CloudProxy server. It incupsulates the following actions
+
+* Connection to **cloudporxy** over wsj1 websocket
+* Subscription to the event
+* Event loop handling
+
+**Note:** At the moment only two event types are supported
+1. Event_SendMessageConfirmation
+2. Event_ReceivedMessage
+
+### Usage of a Cloudproxy client:
+
+* Include the appropriate header to appliciation
+
+ ```
+ #include "cloudproxy-client/cloudproxyclient.h"
+ ```
+
+* Initialization of the CloudProxy client inside the application:
+
+```
+CloudProxyClient* g_cloudproxyclient{nullptr};
+
+g_cloudproxyclient = new CloudProxyClient();
+g_cloudproxyclient->init(port, token.c_str());
+
+```
+
+### Message handling from/to the CloudProxy server:
+
+
+* Subsription to the Event_SendMessageConfirmation
+
+
+
+```
+g_cloudproxyclient->set_event_handler(CloudProxyClient::Event_SendMessageConfirmation, [](json_object* object){
+ json_object *j_result;
+ if(!json_object_object_get_ex(object, "result", &j_result))
+ {
+ qDebug("Can't read confirmation result");
+ return;
+ }
+
+ qDebug("Confirmation result %d", (int)json_object_get_boolean(j_result));
+ });
+
+ ```
+
+
+
+* Subsription to the Event_SendMessageConfirmation
+
+```
+g_cloudproxyclient->set_event_handler(CloudProxyClient::Event_ReceivedMessage, [](json_object* object)
+ json_object *event_data;
+ const char* data_str{nullptr};
+ if(!json_object_object_get_ex(object, "data", &event_data) ||
+ data_str = json_object_get_string(event_data)) == nullptr)
+ {
+ qDebug("Can't read event data");
+ return;
+ }
+
+ qDebug("Received data: %s", data_str);
+ });
+ ```
+
+
+* Message sending:
+
+
+```
+qDebug() << "sendMessage result: " << g_cloudproxyclient->sendMessage("{\"app_key\": \"app_value1111\"}");
+``` \ No newline at end of file
diff --git a/sample/telemetry-cloud-app/app/TelemetryWorker.cpp b/sample/telemetry-cloud-app/app/TelemetryWorker.cpp
new file mode 100755
index 0000000..c277d2b
--- /dev/null
+++ b/sample/telemetry-cloud-app/app/TelemetryWorker.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TelemetryWorker.h"
+#include <QDebug>
+#include <nlohmann/json.hpp>
+#include <time.h>
+#include <stdlib.h>
+
+#include <libcloudproxy.h>
+
+/*
+left up: 56.327 43.981
+right up: 56.327 44.03
+right bottom: 56.3 44.03
+left bottom: 56.3 43.981
+
+start: 56.321674 44.006383
+top: 56.329702 44.021352
+
+diff -0.008028 -0.014969
+coeff lon/lat = 1,8646
+
+
+https://gps-coordinates.org/distance-between-coordinates.php
+*/
+
+
+static double drand(double min, double max)
+{
+ double f = (double)rand() / RAND_MAX;
+ return min + f * (max - min);
+}
+
+
+void TelemetryWorker::send()
+{
+ const double lat_top{56.329702};
+ const double lon_lat_coef{1.8646};
+ const double lat_step{0.001}, lon_step{lat_step*lon_lat_coef};
+
+ if (direction == 0 && lat >= lat_top)
+ {
+ direction = 1;
+ qDebug() << "Change direction to " << direction;
+ }
+ else if (direction == 1 && lat <= init_lat)
+ {
+ direction = 2;
+ qDebug() << "Change direction to " << direction;
+ }
+ else if (direction == 2 && lat <= (init_lat - (lat_top - init_lat)))
+ {
+ direction = 3;
+ qDebug() << "Change direction to " << direction;
+ }
+ else if (direction == 3 && lat >= init_lat)
+ {
+ direction = 0;
+ qDebug() << "Change direction to " << direction;
+ }
+
+
+ if (direction == 0)
+ {
+ lat += lat_step;
+ lon += lon_step;
+ }
+ else if (direction == 1)
+ {
+ lat -= lat_step;
+ lon += lon_step;
+ }
+ else if (direction == 2)
+ {
+ lat -= lat_step;
+ lon -= lon_step;
+ }
+ else if (direction == 3)
+ {
+ lat += lat_step;
+ lon -= lon_step;
+ }
+
+ nlohmann::json jmsg{
+ {"tele_ver", "1.0"},
+ {"lat", lat},
+ {"lon", lon},
+ {"alt", (size_t)(alt + drand(0, 10))},
+ {"speed", (size_t)(speed + drand(20, 30))},
+ {"ts", time(nullptr)}
+ };
+
+ {
+ //WARN: remove
+ const auto& msg{jmsg.dump()};
+ qDebug() << "TelemetryWorker: " << msg.c_str();
+ }
+
+ if (cloudproxyclient)
+ qDebug() << "TelemetryWorker: cloud sendMessage result: " << cloudproxyclient->sendMessage(jmsg.dump());
+
+}
diff --git a/sample/telemetry-cloud-app/app/TelemetryWorker.h b/sample/telemetry-cloud-app/app/TelemetryWorker.h
new file mode 100755
index 0000000..11210cb
--- /dev/null
+++ b/sample/telemetry-cloud-app/app/TelemetryWorker.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <QTimer>
+
+class CloudProxyClient;
+
+class TelemetryWorker : public QTimer
+{
+ Q_OBJECT
+public:
+ TelemetryWorker(CloudProxyClient* cloudproxy, QObject* parent = nullptr)
+ : QTimer(parent),
+ cloudproxyclient{cloudproxy}
+ {
+ }
+
+public slots:
+ void send();
+
+private:
+ CloudProxyClient* cloudproxyclient{nullptr};
+
+ int direction{0};
+ const double init_lat{56.306};
+ const double init_lon{44.070};
+ double lat{init_lat};
+ double lon{init_lon};
+ double alt{300.0};
+ double speed{500.0};
+ uint32_t engine_rpm{3000};
+ int32_t engine_temp{97};
+};
diff --git a/sample/telemetry-cloud-app/app/app.pri b/sample/telemetry-cloud-app/app/app.pri
new file mode 100755
index 0000000..6d710e4
--- /dev/null
+++ b/sample/telemetry-cloud-app/app/app.pri
@@ -0,0 +1,3 @@
+TEMPLATE = app
+QMAKE_LFLAGS += "-Wl,--hash-style=gnu -Wl,--as-needed"
+DESTDIR = $${OUT_PWD}/../package/root/bin
diff --git a/sample/telemetry-cloud-app/app/app.pro b/sample/telemetry-cloud-app/app/app.pro
new file mode 100755
index 0000000..798fa82
--- /dev/null
+++ b/sample/telemetry-cloud-app/app/app.pro
@@ -0,0 +1,32 @@
+TARGET = telemetrycloudapp
+QT += core gui gui-private
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+DEFINES += QT_DEPRECATED_WARNINGS
+
+SOURCES = main.cpp \
+ mainwindow.cpp \
+ TelemetryWorker.cpp
+
+HEADERS += mainwindow.h \
+ ui_mainwindow.h \
+ TelemetryWorker.h
+
+CONFIG += link_pkgconfig
+PKGCONFIG += libhomescreen qtappfw-core libcloudproxy
+
+CONFIG(release, debug|release) {
+ QMAKE_POST_LINK = $(STRIP) --strip-unneeded $(TARGET)
+}
+
+LIBS += -ljson-c -lafbwsc -lsystemd
+
+RESOURCES += \
+ images/images.qrc
+
+include(app.pri)
+
+DISTFILES += \
+ images/AGL_HMI_Blue_Background_NoCar-01.png
+
diff --git a/sample/telemetry-cloud-app/app/images/AGL_HMI_Blue_Background_NoCar-01.png b/sample/telemetry-cloud-app/app/images/AGL_HMI_Blue_Background_NoCar-01.png
new file mode 100755
index 0000000..a76b140
--- /dev/null
+++ b/sample/telemetry-cloud-app/app/images/AGL_HMI_Blue_Background_NoCar-01.png
Binary files differ
diff --git a/sample/telemetry-cloud-app/app/images/images.qrc b/sample/telemetry-cloud-app/app/images/images.qrc
new file mode 100755
index 0000000..78d9b77
--- /dev/null
+++ b/sample/telemetry-cloud-app/app/images/images.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/images">
+ <file>AGL_HMI_Blue_Background_NoCar-01.png</file>
+ </qresource>
+</RCC>
diff --git a/sample/telemetry-cloud-app/app/main.cpp b/sample/telemetry-cloud-app/app/main.cpp
new file mode 100755
index 0000000..ca053ad
--- /dev/null
+++ b/sample/telemetry-cloud-app/app/main.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <QtCore/QUrlQuery>
+#include <QtGui/QGuiApplication>
+#include <QtCore/QCommandLineParser>
+#include <QScopedPointer>
+
+#include "mainwindow.h"
+#include <QApplication>
+#include <QDebug>
+
+#include <libcloudproxy.h>
+
+
+CloudProxyClient* g_cloudproxyclient{nullptr};
+
+
+int main(int argc, char *argv[])
+{
+ QString graphic_role = QString("telemetrycloud");
+
+ QApplication app(argc, argv);
+ app.setDesktopFileName(graphic_role);
+ QScopedPointer<MainWindow> window;
+
+ QCommandLineParser parser;
+ parser.addPositionalArgument("port", app.translate("main", "port for binding"));
+ parser.addPositionalArgument("secret", app.translate("main", "secret for binding"));
+ parser.addHelpOption();
+ parser.addVersionOption();
+ parser.process(app);
+ QStringList positionalArguments = parser.positionalArguments();
+
+ if (positionalArguments.length() == 2)
+ {
+ int port = positionalArguments.takeFirst().toInt();
+ QString secret = positionalArguments.takeFirst();
+ QUrl bindingAddress;
+ bindingAddress.setScheme(QStringLiteral("ws"));
+ bindingAddress.setHost(QStringLiteral("localhost"));
+ bindingAddress.setPort(port);
+ bindingAddress.setPath(QStringLiteral("/api"));
+ QUrlQuery query;
+ query.addQueryItem(QStringLiteral("token"), secret);
+ bindingAddress.setQuery(query);
+
+ std::string token = secret.toStdString();
+ window.reset(new MainWindow(1));
+
+ g_cloudproxyclient = new CloudProxyClient();
+ g_cloudproxyclient->init(port, token.c_str());
+
+ g_cloudproxyclient->set_event_handler(CloudProxyClient::Event_ReceivedMessage, [&window](json_object* object){
+ qDebug("CloudProxyClient::Event_ReceivedMessage: object ptr %p", object);
+
+ const char* str = object ? json_object_to_json_string_ext(object, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY) : "<obj_null>";
+ if (!str)
+ str = "<empty>";
+ qDebug("Event_SendMessageConfirmation: %s", str);
+
+ json_object *event_data;
+ const char* data_str{nullptr};
+ if(!json_object_object_get_ex(object, "data", &event_data) ||
+ (data_str = json_object_get_string(event_data)) == nullptr)
+ {
+ qDebug("Can't read event data");
+ return;
+ }
+
+ window->updateState(QString(data_str));
+ qDebug("Application received data: %s", data_str);
+ });
+
+ window->show();
+ }
+
+ return app.exec();
+}
diff --git a/sample/telemetry-cloud-app/app/mainwindow.cpp b/sample/telemetry-cloud-app/app/mainwindow.cpp
new file mode 100755
index 0000000..2e8796c
--- /dev/null
+++ b/sample/telemetry-cloud-app/app/mainwindow.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include <QDebug>
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <nlohmann/json.hpp>
+
+
+#include <libcloudproxy.h>
+extern CloudProxyClient* g_cloudproxyclient;
+
+
+MainWindow::MainWindow(double scale_factor, QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MainWindow)
+{
+ ui->setupUi(scale_factor, this);
+
+ //AGL style
+ setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
+ this->setStyleSheet(
+ "background-image:url(:/images/AGL_HMI_Blue_Background_NoCar-01.png) 0 0 0 0 stretch stretch; background: transparent;" );
+}
+
+void MainWindow::updateState(QVariant recvMsg)
+{
+ if (!recvMsg.isValid())
+ return;
+
+ // expected format: {"message": "bla-bla"}
+ std::string cloud_msg;
+ try
+ {
+ const std::string& msg = recvMsg.toString().toStdString();
+ if (msg.empty())
+ {
+ qDebug() << "Received message is empty";
+ }
+ else
+ {
+ const nlohmann::json& jmsg = nlohmann::json::parse(msg);
+ cloud_msg = jmsg["message"].get<std::string>();
+ }
+ }
+ catch (std::exception& ex)
+ {
+ qDebug() << "Can't parse incomming message: " << ex.what();
+ }
+
+ QString str = QString::asprintf("Cloud info: %s", cloud_msg.c_str());
+ ui->stateLabel->setText(str);
+}
+
+void MainWindow::startMsgButtonClick()
+{
+ qDebug() << "MainWindow::startMsgButtonClick()";
+
+ if (started)
+ ui->startMsgButton->setText("Start");
+ else
+ ui->startMsgButton->setText("Stop");
+ started = !started;
+
+ if (worker)
+ {
+ worker->stop();
+ worker.reset();
+ qDebug() << "Worker destroyed";
+ }
+
+ if (started)
+ {
+ worker.reset(new TelemetryWorker(g_cloudproxyclient, this));
+ connect(worker.get(), SIGNAL(timeout()), worker.get(), SLOT(send()));
+ worker->start(1001);
+ }
+}
+
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
diff --git a/sample/telemetry-cloud-app/app/mainwindow.h b/sample/telemetry-cloud-app/app/mainwindow.h
new file mode 100755
index 0000000..ce21845
--- /dev/null
+++ b/sample/telemetry-cloud-app/app/mainwindow.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QVariant>
+#include <QScopedPointer>
+#include <memory>
+
+#include "TelemetryWorker.h"
+
+
+namespace Ui {
+ class MainWindow;
+}
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(double scale_factor, QWidget *parent = 0);
+ ~MainWindow();
+
+public slots:
+ void updateState(QVariant recvMsg);
+
+private slots:
+ void startMsgButtonClick();
+
+private:
+ Ui::MainWindow *ui;
+ bool started{false};
+ QScopedPointer<TelemetryWorker> worker;
+};
+
+#endif // MAINWINDOW_H
diff --git a/sample/telemetry-cloud-app/app/ui_mainwindow.h b/sample/telemetry-cloud-app/app/ui_mainwindow.h
new file mode 100755
index 0000000..5dbcbd5
--- /dev/null
+++ b/sample/telemetry-cloud-app/app/ui_mainwindow.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UI_MAINWINDOW_H
+#define UI_MAINWINDOW_H
+
+#include <QtCore/QVariant>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QMainWindow>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QFrame>
+#include <QtWidgets/QGroupBox>
+#include <QtWidgets/QRadioButton>
+#include <QtWidgets/QComboBox>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_MainWindow
+{
+public:
+ QWidget *centralWidget{nullptr};
+ QPushButton *startMsgButton{nullptr};
+ QLabel *stateLabel{nullptr};
+
+ void setupUi(double scale_factor, QMainWindow *MainWindow)
+ {
+ if (MainWindow->objectName().isEmpty())
+ MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
+ MainWindow->resize(1080*scale_factor, 1400*scale_factor);
+ centralWidget = new QWidget(MainWindow);
+ centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
+
+ //QString style("color: white; font-size: 24px");
+ QString style("color: white");
+
+ startMsgButton = new QPushButton(centralWidget);
+ startMsgButton->setObjectName(QString::fromUtf8("startMsgButton"));
+ startMsgButton->setGeometry(QRect((540-242/2)*scale_factor, 20*scale_factor, 242*scale_factor, 64*scale_factor));
+ startMsgButton->setStyleSheet(style);
+
+ stateLabel = new QLabel(centralWidget);
+ stateLabel->setObjectName(QString::fromUtf8("label"));
+ stateLabel->setGeometry(QRect(40*scale_factor, 180*scale_factor, 1000*scale_factor, 420*scale_factor));
+ stateLabel->setWordWrap(true);
+ stateLabel->setAlignment(Qt::AlignTop);
+ stateLabel->setStyleSheet(style);
+
+ MainWindow->setCentralWidget(centralWidget);
+
+ QObject::connect(startMsgButton, SIGNAL(clicked()), MainWindow, SLOT(startMsgButtonClick()));
+
+ retranslateUi(MainWindow);
+
+ QMetaObject::connectSlotsByName(MainWindow);
+ } // setupUi
+
+ void retranslateUi(QMainWindow *MainWindow)
+ {
+ MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr));
+ startMsgButton->setText(QApplication::translate("MainWindow", "Start", nullptr));
+ } // retranslateUi
+};
+
+namespace Ui {
+ class MainWindow: public Ui_MainWindow {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_MAINWINDOW_H
diff --git a/sample/telemetry-cloud-app/autobuild/agl/autobuild b/sample/telemetry-cloud-app/autobuild/agl/autobuild
new file mode 100755
index 0000000..bbbc13e
--- /dev/null
+++ b/sample/telemetry-cloud-app/autobuild/agl/autobuild
@@ -0,0 +1,110 @@
+#!/usr/bin/make -f
+# Copyright (C) 2015 - 2018 "IoT.bzh"
+# Copyright (C) 2020 Konsulko Group
+# Author "Romain Forlot" <romain.forlot@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+THISFILE := $(lastword $(MAKEFILE_LIST))
+ROOT_DIR := $(abspath $(dir $(THISFILE))/../..)
+
+# Build directories
+# Note that the debug directory is defined in relation to the release
+# directory (BUILD_DIR), this needs to be kept in mind if over-riding
+# it and building that widget types, the specific widget type variable
+# (e.g. BUILD_DIR_DEBUG) may also need to be specified to yield the
+# desired output hierarchy.
+BUILD_DIR = $(ROOT_DIR)/build
+BUILD_DIR_DEBUG = $(abspath $(BUILD_DIR)/../build-debug)
+
+# Output directory variable for use in pattern rules.
+# This is intended for internal use only, hence the explicit override
+# definition.
+override OUTPUT_DIR = $(BUILD_DIR)
+
+# Final install directory for widgets
+DEST = $(OUTPUT_DIR)
+
+# Default build type for release builds
+BUILD_TYPE = release
+
+.PHONY: all help update install distclean
+.PHONY: clean clean-release clean-debug clean-all
+.PHONY: configure configure-release configure-debug
+.PHONY: build build-release build-debug build-all
+.PHONY: package package-release package-debug package-all
+
+help:
+ @echo "List of targets available:"
+ @echo ""
+ @echo "- all"
+ @echo "- help"
+ @echo "- clean"
+ @echo "- distclean"
+ @echo "- configure"
+ @echo "- build: compilation, link and prepare files for package into a widget"
+ @echo "- package: output a widget file '*.wgt'"
+ @echo "- install: install in $(DEST) directory"
+ @echo ""
+ @echo "Usage: ./autobuild/agl/autobuild package DEST=${HOME}/opt"
+ @echo "Don't use your build dir as DEST as wgt file is generated at this location"
+
+all: package-all
+
+# Target specific variable over-rides so static pattern rules can be
+# used for the various type-specific targets.
+
+configure-debug build-debug package-debug clean-debug: OUTPUT_DIR = $(BUILD_DIR_DEBUG)
+configure-debug build-debug package-debug: BUILD_TYPE = debug
+
+clean-release clean-debug:
+ @if [ -d $(OUTPUT_DIR) ]; then \
+ $(MAKE) -C $(OUTPUT_DIR) $(CLEAN_ARGS) clean; \
+ else \
+ echo Nothing to clean; \
+ fi
+
+clean: clean-release
+
+clean-all: clean-release clean-debug
+
+distclean: clean-all
+
+configure-release configure-debug:
+ @mkdir -p $(OUTPUT_DIR)
+ @if [ ! -f $(OUTPUT_DIR)/Makefile ]; then \
+ (cd $(OUTPUT_DIR) && qmake CONFIG+=$(BUILD_TYPE) $(CONFIGURE_ARGS) $(ROOT_DIR)); \
+ fi
+
+configure: configure-release
+
+build-release build-debug: build-%: configure-%
+ @$(MAKE) -C $(OUTPUT_DIR) $(BUILD_ARGS) all
+
+build: build-release
+
+build-all: build-release build-debug
+
+package-release package-debug: package-%: build-%
+ @cp $(OUTPUT_DIR)/package/*.wgt $(OUTPUT_DIR)/
+ @if [ "$(abspath $(DEST))" != "$(abspath $(OUTPUT_DIR))" ]; then \
+ mkdir -p $(DEST) && cp $(OUTPUT_DIR)/*.wgt $(DEST); \
+ fi
+
+
+package: package-release
+
+package-all: package-release package-debug
+
+install: build
+ @$(MAKE) -C $(BUILD_DIR) $(INSTALL_ARGS) install
diff --git a/sample/telemetry-cloud-app/autobuild/linux/autobuild b/sample/telemetry-cloud-app/autobuild/linux/autobuild
new file mode 100755
index 0000000..bbbc13e
--- /dev/null
+++ b/sample/telemetry-cloud-app/autobuild/linux/autobuild
@@ -0,0 +1,110 @@
+#!/usr/bin/make -f
+# Copyright (C) 2015 - 2018 "IoT.bzh"
+# Copyright (C) 2020 Konsulko Group
+# Author "Romain Forlot" <romain.forlot@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+THISFILE := $(lastword $(MAKEFILE_LIST))
+ROOT_DIR := $(abspath $(dir $(THISFILE))/../..)
+
+# Build directories
+# Note that the debug directory is defined in relation to the release
+# directory (BUILD_DIR), this needs to be kept in mind if over-riding
+# it and building that widget types, the specific widget type variable
+# (e.g. BUILD_DIR_DEBUG) may also need to be specified to yield the
+# desired output hierarchy.
+BUILD_DIR = $(ROOT_DIR)/build
+BUILD_DIR_DEBUG = $(abspath $(BUILD_DIR)/../build-debug)
+
+# Output directory variable for use in pattern rules.
+# This is intended for internal use only, hence the explicit override
+# definition.
+override OUTPUT_DIR = $(BUILD_DIR)
+
+# Final install directory for widgets
+DEST = $(OUTPUT_DIR)
+
+# Default build type for release builds
+BUILD_TYPE = release
+
+.PHONY: all help update install distclean
+.PHONY: clean clean-release clean-debug clean-all
+.PHONY: configure configure-release configure-debug
+.PHONY: build build-release build-debug build-all
+.PHONY: package package-release package-debug package-all
+
+help:
+ @echo "List of targets available:"
+ @echo ""
+ @echo "- all"
+ @echo "- help"
+ @echo "- clean"
+ @echo "- distclean"
+ @echo "- configure"
+ @echo "- build: compilation, link and prepare files for package into a widget"
+ @echo "- package: output a widget file '*.wgt'"
+ @echo "- install: install in $(DEST) directory"
+ @echo ""
+ @echo "Usage: ./autobuild/agl/autobuild package DEST=${HOME}/opt"
+ @echo "Don't use your build dir as DEST as wgt file is generated at this location"
+
+all: package-all
+
+# Target specific variable over-rides so static pattern rules can be
+# used for the various type-specific targets.
+
+configure-debug build-debug package-debug clean-debug: OUTPUT_DIR = $(BUILD_DIR_DEBUG)
+configure-debug build-debug package-debug: BUILD_TYPE = debug
+
+clean-release clean-debug:
+ @if [ -d $(OUTPUT_DIR) ]; then \
+ $(MAKE) -C $(OUTPUT_DIR) $(CLEAN_ARGS) clean; \
+ else \
+ echo Nothing to clean; \
+ fi
+
+clean: clean-release
+
+clean-all: clean-release clean-debug
+
+distclean: clean-all
+
+configure-release configure-debug:
+ @mkdir -p $(OUTPUT_DIR)
+ @if [ ! -f $(OUTPUT_DIR)/Makefile ]; then \
+ (cd $(OUTPUT_DIR) && qmake CONFIG+=$(BUILD_TYPE) $(CONFIGURE_ARGS) $(ROOT_DIR)); \
+ fi
+
+configure: configure-release
+
+build-release build-debug: build-%: configure-%
+ @$(MAKE) -C $(OUTPUT_DIR) $(BUILD_ARGS) all
+
+build: build-release
+
+build-all: build-release build-debug
+
+package-release package-debug: package-%: build-%
+ @cp $(OUTPUT_DIR)/package/*.wgt $(OUTPUT_DIR)/
+ @if [ "$(abspath $(DEST))" != "$(abspath $(OUTPUT_DIR))" ]; then \
+ mkdir -p $(DEST) && cp $(OUTPUT_DIR)/*.wgt $(DEST); \
+ fi
+
+
+package: package-release
+
+package-all: package-release package-debug
+
+install: build
+ @$(MAKE) -C $(BUILD_DIR) $(INSTALL_ARGS) install
diff --git a/sample/telemetry-cloud-app/package/config.xml b/sample/telemetry-cloud-app/package/config.xml
new file mode 100755
index 0000000..d1300ab
--- /dev/null
+++ b/sample/telemetry-cloud-app/package/config.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" id="telemetrycloudapp" version="0.1">
+ <name>CloudTelemetry</name>
+ <icon src="icon.svg"/>
+ <content src="bin/telemetrycloudapp" type="application/vnd.agl.native"/>
+ <description>Test Cloud App</description>
+ <author>Mera</author>
+ <license>APL 2.0</license>
+ <feature name="urn:AGL:widget:required-api">
+ <param name="homescreen" value="ws"/>
+ <param name="cloudproxy" value="ws"/>
+ </feature>
+ <feature name="urn:AGL:widget:required-permission">
+ <param name="urn:AGL:permission::public:no-htdocs" value="required"/>
+ <param name="urn:AGL:permission::public:display" value="required" />
+ </feature>
+</widget>
diff --git a/sample/telemetry-cloud-app/package/icon.svg b/sample/telemetry-cloud-app/package/icon.svg
new file mode 100755
index 0000000..b9b8e67
--- /dev/null
+++ b/sample/telemetry-cloud-app/package/icon.svg
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:i="&amp;#38;ns_ai;"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ x="0px"
+ y="0px"
+ viewBox="0 0 320 320"
+ style="enable-background:new 0 0 320 320;"
+ xml:space="preserve"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="icon.svg"><metadata
+ id="metadata1292"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs1290" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="2560"
+ inkscape:window-height="1464"
+ id="namedview1288"
+ showgrid="false"
+ inkscape:zoom="4.17193"
+ inkscape:cx="183.76952"
+ inkscape:cy="191.17869"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" /><style
+ type="text/css"
+ id="style4">
+ .st0{display:none;}
+ .st1{display:inline;}
+ .st2{opacity:0.4;fill:url(#SVGID_1_);}
+ .st3{fill:url(#SVGID_2_);}
+ .st4{fill:#FFFFFF;}
+ .st5{font-family:'Roboto-Regular';}
+ .st6{font-size:25px;}
+ .st7{letter-spacing:6;}
+ .st8{fill:url(#SVGID_3_);}
+ .st9{fill:url(#SVGID_4_);}
+ .st10{fill:url(#SVGID_5_);}
+ .st11{fill:url(#SVGID_6_);}
+ .st12{fill:url(#SVGID_7_);}
+ .st13{fill:url(#SVGID_8_);}
+ .st14{fill:url(#SVGID_9_);}
+ .st15{fill:url(#SVGID_10_);}
+ .st16{fill:url(#SVGID_11_);}
+ .st17{fill:url(#SVGID_12_);}
+ .st18{fill:url(#SVGID_13_);}
+ .st19{fill:url(#SVGID_14_);}
+ .st20{fill:url(#SVGID_15_);}
+ .st21{fill:url(#SVGID_16_);}
+ .st22{fill:url(#SVGID_17_);}
+ .st23{fill:url(#SVGID_18_);}
+ .st24{opacity:0.29;}
+ .st25{fill:url(#SVGID_19_);}
+ .st26{fill:url(#SVGID_20_);}
+ .st27{fill:url(#SVGID_21_);}
+ .st28{fill:url(#SVGID_22_);}
+ .st29{fill:url(#SVGID_23_);}
+ .st30{fill:url(#SVGID_24_);}
+ .st31{fill:url(#SVGID_25_);}
+ .st32{fill:url(#SVGID_26_);}
+ .st33{fill:url(#SVGID_27_);}
+ .st34{fill:url(#SVGID_28_);}
+ .st35{fill:url(#SVGID_29_);}
+ .st36{fill:url(#SVGID_30_);}
+ .st37{fill:url(#SVGID_31_);}
+ .st38{fill:url(#SVGID_32_);}
+ .st39{fill:url(#SVGID_33_);}
+ .st40{fill:url(#SVGID_34_);}
+ .st41{fill:url(#SVGID_35_);}
+ .st42{fill:url(#SVGID_36_);}
+ .st43{opacity:0.4;fill:url(#SVGID_37_);}
+ .st44{fill:url(#SVGID_38_);}
+ .st45{fill:url(#SVGID_39_);}
+ .st46{fill:url(#SVGID_40_);}
+ .st47{fill:url(#SVGID_41_);}
+ .st48{fill:url(#SVGID_42_);}
+ .st49{fill:url(#SVGID_43_);}
+ .st50{fill:url(#SVGID_44_);}
+ .st51{display:inline;opacity:0.29;}
+ .st52{display:inline;fill:url(#SVGID_45_);}
+ .st53{display:inline;fill:url(#SVGID_46_);}
+ .st54{display:inline;fill:#FFFFFF;}
+ .st55{display:inline;fill:url(#SVGID_47_);}
+ .st56{display:inline;fill:url(#SVGID_48_);}
+ .st57{display:inline;fill:url(#SVGID_49_);}
+ .st58{display:inline;fill:url(#SVGID_50_);}
+ .st59{display:inline;fill:url(#SVGID_51_);}
+ .st60{display:inline;fill:url(#SVGID_52_);}
+ .st61{opacity:0.4;fill:url(#SVGID_53_);}
+ .st62{fill:url(#SVGID_54_);}
+ .st63{fill:url(#SVGID_55_);}
+ .st64{fill:url(#SVGID_56_);}
+ .st65{fill:url(#SVGID_57_);}
+ .st66{fill:url(#SVGID_58_);}
+ .st67{opacity:0.4;fill:url(#SVGID_59_);}
+ .st68{fill:url(#SVGID_60_);}
+ .st69{fill:url(#SVGID_61_);}
+ .st70{fill:url(#SVGID_62_);}
+ .st71{fill:url(#SVGID_63_);}
+ .st72{fill:url(#SVGID_64_);}
+ .st73{fill:url(#SVGID_65_);}
+ .st74{fill:url(#SVGID_66_);}
+ .st75{fill:url(#SVGID_67_);}
+ .st76{fill:url(#SVGID_68_);}
+ .st77{fill:url(#SVGID_69_);}
+ .st78{fill:url(#SVGID_70_);}
+ .st79{fill:url(#SVGID_71_);}
+ .st80{fill:url(#SVGID_72_);}
+ .st81{fill:url(#SVGID_73_);}
+ .st82{fill:url(#SVGID_74_);}
+ .st83{fill:url(#SVGID_75_);}
+ .st84{fill:url(#SVGID_76_);}
+ .st85{fill:url(#SVGID_77_);}
+ .st86{fill:url(#SVGID_78_);}
+ .st87{fill:url(#SVGID_79_);}
+ .st88{fill:url(#SVGID_80_);}
+ .st89{fill:url(#SVGID_81_);}
+ .st90{fill:url(#SVGID_82_);}
+ .st91{fill:url(#SVGID_83_);}
+ .st92{fill:url(#SVGID_84_);}
+ .st93{fill:url(#SVGID_85_);}
+ .st94{fill:url(#SVGID_86_);}
+ .st95{opacity:0.4;fill:url(#SVGID_87_);}
+ .st96{fill:url(#SVGID_88_);}
+ .st97{fill:url(#SVGID_89_);}
+ .st98{fill:url(#SVGID_90_);}
+ .st99{fill:url(#SVGID_91_);}
+ .st100{fill:url(#SVGID_92_);}
+ .st101{fill:url(#SVGID_93_);}
+ .st102{fill:url(#SVGID_94_);}
+ .st103{opacity:0.4;fill:url(#SVGID_95_);}
+ .st104{fill:url(#SVGID_96_);}
+ .st105{fill:url(#SVGID_97_);}
+ .st106{fill:url(#SVGID_98_);}
+ .st107{fill:url(#SVGID_99_);}
+ .st108{fill:url(#SVGID_100_);}
+ .st109{fill:url(#SVGID_101_);}
+ .st110{display:inline;fill:url(#SVGID_102_);}
+ .st111{display:inline;fill:url(#SVGID_103_);}
+ .st112{fill:url(#SVGID_104_);}
+ .st113{fill:url(#SVGID_105_);}
+ .st114{fill:url(#SVGID_106_);}
+ .st115{fill:url(#SVGID_107_);}
+ .st116{fill:url(#SVGID_108_);}
+ .st117{opacity:0.4;fill:url(#SVGID_109_);}
+ .st118{fill:url(#SVGID_110_);}
+ .st119{fill:url(#SVGID_111_);}
+ .st120{fill:url(#SVGID_112_);}
+ .st121{fill:url(#SVGID_113_);}
+ .st122{fill:url(#SVGID_114_);}
+ .st123{opacity:0.4;fill:url(#SVGID_115_);}
+ .st124{fill:url(#SVGID_116_);}
+ .st125{fill:url(#SVGID_117_);}
+ .st126{fill:url(#SVGID_118_);}
+ .st127{display:inline;fill:url(#SVGID_119_);}
+ .st128{display:inline;fill:url(#SVGID_120_);}
+ .st129{fill:url(#SVGID_121_);}
+ .st130{fill:url(#SVGID_122_);}
+</style><switch
+ id="switch6"><g
+ i:extraneous="self"
+ id="g8"><g
+ id="Multimedia_Inactive_copy"><circle
+ class="st24"
+ cx="159.7"
+ cy="133.4"
+ r="101.9"
+ id="circle884" /><linearGradient
+ id="SVGID_91_"
+ gradientUnits="userSpaceOnUse"
+ x1="115.9317"
+ y1="254.1836"
+ x2="256.3852"
+ y2="-133.5267"><stop
+ offset="0"
+ style="stop-color:#8BC53F"
+ id="stop887" /><stop
+ offset="2.015080e-02"
+ style="stop-color:#7CCB56;stop-opacity:0.9678"
+ id="stop889" /><stop
+ offset="6.089833e-02"
+ style="stop-color:#62D67D;stop-opacity:0.9028"
+ id="stop891" /><stop
+ offset="0.1057"
+ style="stop-color:#4BDFA0;stop-opacity:0.8312"
+ id="stop893" /><stop
+ offset="0.1543"
+ style="stop-color:#38E7BE;stop-opacity:0.7537"
+ id="stop895" /><stop
+ offset="0.2077"
+ style="stop-color:#28EED6;stop-opacity:0.6684"
+ id="stop897" /><stop
+ offset="0.2681"
+ style="stop-color:#1CF3E8;stop-opacity:0.572"
+ id="stop899" /><stop
+ offset="0.3394"
+ style="stop-color:#13F6F5;stop-opacity:0.4581"
+ id="stop901" /><stop
+ offset="0.4323"
+ style="stop-color:#0EF8FD;stop-opacity:0.3098"
+ id="stop903" /><stop
+ offset="0.6264"
+ style="stop-color:#0DF9FF;stop-opacity:0"
+ id="stop905" /></linearGradient><circle
+ class="st99"
+ cx="159.7"
+ cy="133.4"
+ r="101.9"
+ id="circle907" /><linearGradient
+ id="SVGID_92_"
+ gradientUnits="userSpaceOnUse"
+ x1="4.0481"
+ y1="287.9492"
+ x2="320.4859"
+ y2="-15.4029"
+ gradientTransform="matrix(1 5.464556e-03 -5.464556e-03 1 -2.0192 -3.0212)"><stop
+ offset="0"
+ style="stop-color:#59FF7F"
+ id="stop910" /><stop
+ offset="1"
+ style="stop-color:#6BFBFF"
+ id="stop912" /></linearGradient><path
+ class="st100"
+ d="M160,238.8c-0.2,0-0.4,0-0.6,0c-58-0.3-104.9-47.7-104.6-105.7C55.2,75.3,102.3,28.5,160,28.5 c0.2,0,0.4,0,0.6,0c58,0.3,104.9,47.7,104.6,105.7l0,0C264.8,192,217.7,238.8,160,238.8z M160,32.2 c-55.7,0-101.2,45.2-101.5,100.9c-0.3,55.9,45,101.7,100.9,102c0.2,0,0.4,0,0.6,0c55.7,0,101.2-45.2,101.5-100.9 c0.3-55.9-45-101.7-100.9-102C160.4,32.2,160.2,32.2,160,32.2z"
+ id="path914" /><g
+ id="g916"><text
+ transform="matrix(1 0 0 1 53.5841 284.7119)"
+ class="st4 st5 st6 st7"
+ id="text918">VIDEOPLAYER
+</text>
+<linearGradient
+ id="SVGID_94_"
+ gradientUnits="userSpaceOnUse"
+ x1="145.3286"
+ y1="203.8951"
+ x2="191.6285"
+ y2="70.3637"><stop
+ offset="0"
+ style="stop-color:#59FF7F"
+ id="stop928" /><stop
+ offset="1"
+ style="stop-color:#6BFBFF"
+ id="stop930" /></linearGradient><polygon
+ class="st102"
+ points="125,75 125,200 225,137.5 "
+ id="polygon932"
+ style="fill:url(#SVGID_94_)" /></g></g></g></switch></svg> \ No newline at end of file
diff --git a/sample/telemetry-cloud-app/package/package.pro b/sample/telemetry-cloud-app/package/package.pro
new file mode 100755
index 0000000..7a138a3
--- /dev/null
+++ b/sample/telemetry-cloud-app/package/package.pro
@@ -0,0 +1,28 @@
+
+DISTFILES = icon.svg config.xml
+
+copy_icon.target = $$OUT_PWD/root/icon.svg
+copy_icon.depends = $$_PRO_FILE_PWD_/icon.svg
+copy_icon.commands = $(COPY_FILE) \"$$replace(copy_icon.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_icon.target, /, $$QMAKE_DIR_SEP)\"
+QMAKE_EXTRA_TARGETS += copy_icon
+PRE_TARGETDEPS += $$copy_icon.target
+
+copy_config.target = $$OUT_PWD/root/config.xml
+copy_config.depends = $$_PRO_FILE_PWD_/config.xml
+copy_config.commands = $(COPY_FILE) \"$$replace(copy_config.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_config.target, /, $$QMAKE_DIR_SEP)\"
+QMAKE_EXTRA_TARGETS += copy_config
+PRE_TARGETDEPS += $$copy_config.target
+
+WGT_TYPE =
+CONFIG(debug, debug|release) {
+ WGT_TYPE = -debug
+}
+
+wgt.target = package
+wgt.commands = wgtpkg-pack -f -o telemetrycloudapp$${WGT_TYPE}.wgt root
+
+QMAKE_EXTRA_TARGETS += wgt
+
+deploy.files = telemetrycloudapp.wgt
+deploy.path = /usr/AGL/apps/autoinstall
+INSTALLS += deploy
diff --git a/sample/telemetry-cloud-app/telemetrycloudapp.pro b/sample/telemetry-cloud-app/telemetrycloudapp.pro
new file mode 100755
index 0000000..579a952
--- /dev/null
+++ b/sample/telemetry-cloud-app/telemetrycloudapp.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS = app package
+package.depends += app
diff --git a/sample/test-cloud-app/app/app.pri b/sample/test-cloud-app/app/app.pri
new file mode 100755
index 0000000..6d710e4
--- /dev/null
+++ b/sample/test-cloud-app/app/app.pri
@@ -0,0 +1,3 @@
+TEMPLATE = app
+QMAKE_LFLAGS += "-Wl,--hash-style=gnu -Wl,--as-needed"
+DESTDIR = $${OUT_PWD}/../package/root/bin
diff --git a/sample/test-cloud-app/app/app.pro b/sample/test-cloud-app/app/app.pro
new file mode 100755
index 0000000..9b72850
--- /dev/null
+++ b/sample/test-cloud-app/app/app.pro
@@ -0,0 +1,31 @@
+TARGET = testcloudapp
+QT += core gui gui-private
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+DEFINES += QT_DEPRECATED_WARNINGS
+DEFINES += APP_INSTANCE_NUM='\\"1\\"'
+
+SOURCES = main.cpp \
+ mainwindow.cpp \
+
+HEADERS += mainwindow.h \
+ ui_mainwindow.h \
+
+CONFIG += link_pkgconfig
+PKGCONFIG += libcloudproxy qtappfw-core
+
+CONFIG(release, debug|release) {
+ QMAKE_POST_LINK = $(STRIP) --strip-unneeded $(TARGET)
+}
+
+LIBS += -ljson-c -lafbwsc -lsystemd
+
+RESOURCES += \
+ images/images.qrc
+
+include(app.pri)
+
+DISTFILES += \
+ images/AGL_HMI_Blue_Background_NoCar-01.png
+
diff --git a/sample/test-cloud-app/app/images/AGL_HMI_Blue_Background_NoCar-01.png b/sample/test-cloud-app/app/images/AGL_HMI_Blue_Background_NoCar-01.png
new file mode 100755
index 0000000..a76b140
--- /dev/null
+++ b/sample/test-cloud-app/app/images/AGL_HMI_Blue_Background_NoCar-01.png
Binary files differ
diff --git a/sample/test-cloud-app/app/images/images.qrc b/sample/test-cloud-app/app/images/images.qrc
new file mode 100755
index 0000000..78d9b77
--- /dev/null
+++ b/sample/test-cloud-app/app/images/images.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/images">
+ <file>AGL_HMI_Blue_Background_NoCar-01.png</file>
+ </qresource>
+</RCC>
diff --git a/sample/test-cloud-app/app/main.cpp b/sample/test-cloud-app/app/main.cpp
new file mode 100755
index 0000000..6918e97
--- /dev/null
+++ b/sample/test-cloud-app/app/main.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <QtCore/QUrlQuery>
+#include <QtGui/QGuiApplication>
+#include <QtCore/QCommandLineParser>
+#include <QScopedPointer>
+
+#include "mainwindow.h"
+#include <QApplication>
+#include <QDebug>
+
+#include "libcloudproxy.h"
+
+CloudProxyClient* g_cloudproxyclient{nullptr};
+
+
+int main(int argc, char *argv[])
+{
+ QString graphic_role = QString("cloudapp") + QString(APP_INSTANCE_NUM);
+
+ QApplication app(argc, argv);
+ app.setDesktopFileName(graphic_role);
+ QScopedPointer<MainWindow> window;
+
+ QCommandLineParser parser;
+ parser.addPositionalArgument("port", app.translate("main", "port for binding"));
+ parser.addPositionalArgument("secret", app.translate("main", "secret for binding"));
+ parser.addHelpOption();
+ parser.addVersionOption();
+ parser.process(app);
+ QStringList positionalArguments = parser.positionalArguments();
+
+ if (positionalArguments.length() == 2)
+ {
+ int port = positionalArguments.takeFirst().toInt();
+ QString secret = positionalArguments.takeFirst();
+ QUrl bindingAddress;
+ bindingAddress.setScheme(QStringLiteral("ws"));
+ bindingAddress.setHost(QStringLiteral("localhost"));
+ bindingAddress.setPort(port);
+ bindingAddress.setPath(QStringLiteral("/api"));
+ QUrlQuery query;
+ query.addQueryItem(QStringLiteral("token"), secret);
+ bindingAddress.setQuery(query);
+
+ std::string token = secret.toStdString();
+ window.reset(new MainWindow(1));
+
+ g_cloudproxyclient = new CloudProxyClient();
+ g_cloudproxyclient->init(port, token.c_str());
+
+ static int i_confirm_good{0}, i_confirm_bad{0}, i_recv{0};
+ g_cloudproxyclient->set_event_handler(CloudProxyClient::Event_SendMessageConfirmation, [&window](json_object* object){
+ qDebug("CloudProxyClient::Event_SendMessageConfirmation: object ptr %p", object);
+
+ const char* str = object ? json_object_to_json_string_ext(object, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY) : "<obj_null>";
+ if (!str)
+ str = "<empty>";
+ qDebug("Event_SendMessageConfirmation: %s", str);
+
+ json_object *j_result;
+ if(!json_object_object_get_ex(object, "result", &j_result))
+ {
+ qDebug("Can't read confirmation result");
+ return;
+ }
+
+ int result = (int)json_object_get_boolean(j_result);
+
+ if (result)
+ ++i_confirm_good;
+ else
+ ++i_confirm_bad;
+
+ window->updateStat(i_confirm_good, i_confirm_bad, i_recv, QVariant());
+ qDebug("Application received confirmation result [good: %d, bad: %d]: %d", i_confirm_good, i_confirm_bad, result);
+ });
+ g_cloudproxyclient->set_event_handler(CloudProxyClient::Event_ReceivedMessage, [&window](json_object* object){
+ qDebug("CloudProxyClient::Event_ReceivedMessage: object ptr %p", object);
+
+ const char* str = object ? json_object_to_json_string_ext(object, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY) : "<obj_null>";
+ if (!str)
+ str = "<empty>";
+ qDebug("Event_SendMessageConfirmation: %s", str);
+
+ json_object *event_data;
+ const char* data_str{nullptr};
+ if(!json_object_object_get_ex(object, "data", &event_data) ||
+ (data_str = json_object_get_string(event_data)) == nullptr)
+ {
+ qDebug("Can't read event data");
+ return;
+ }
+
+ ++i_recv;
+ window->updateStat(i_confirm_good, i_confirm_bad, i_recv, QString(data_str));
+ qDebug("Application received data [count: %d, good: %d, bad %d]: %s", i_recv, i_confirm_good, i_confirm_bad, data_str);
+ });
+
+
+ window->show();
+ }
+
+ return app.exec();
+}
diff --git a/sample/test-cloud-app/app/main.cpp.save b/sample/test-cloud-app/app/main.cpp.save
new file mode 100755
index 0000000..8236ada
--- /dev/null
+++ b/sample/test-cloud-app/app/main.cpp.save
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <QtCore/QUrlQuery>
+#include <QtGui/QGuiApplication>
+#include <QtCore/QCommandLineParser>
+#include <QScopedPointer>
+
+#include "mainwindow.h"
+#include <QApplication>
+#include <QDebug>
+
+#include "cloudproxy-client/cloudproxyclient.h"
+
+
+CloudProxyClient* g_cloudproxyclient{nullptr};
+
+
+int main(int argc, char *argv[])
+{
+ QString graphic_role = QString("cloudapp") + QString(APP_INSTANCE_NUM);
+
+ QApplication app(argc, argv);
+ app.setDesktopFileName(graphic_role);
+ QScopedPointer<MainWindow> window;
+
+ QCommandLineParser parser;
+ parser.addPositionalArgument("port", app.translate("main", "port for binding"));
+ parser.addPositionalArgument("secret", app.translate("main", "secret for binding"));
+ parser.addHelpOption();
+ parser.addVersionOption();
+ parser.process(app);
+ QStringList positionalArguments = parser.positionalArguments();
+
+ if (positionalArguments.length() == 2)
+ {
+ int port = positionalArguments.takeFirst().toInt();
+ QString secret = positionalArguments.takeFirst();
+ QUrl bindingAddress;
+ bindingAddress.setScheme(QStringLiteral("ws"));
+ bindingAddress.setHost(QStringLiteral("localhost"));
+ bindingAddress.setPort(port);
+ bindingAddress.setPath(QStringLiteral("/api"));
+ QUrlQuery query;
+ query.addQueryItem(QStringLiteral("token"), secret);
+ bindingAddress.setQuery(query);
+ std::string token = secret.toStdString();
+ LibHomeScreen* hs = new LibHomeScreen();
+ QLibWindowmanager* qwm = new QLibWindowmanager();
+
+ // WindowManager
+ if(qwm->init(port,secret) != 0){
+ exit(EXIT_FAILURE);
+ }
+ AGLScreenInfo screenInfo(qwm->get_scale_factor());
+ window.reset(new MainWindow(screenInfo.scale_factor()));
+
+ // Request a surface as described in layers.json windowmanager’s file
+ if (qwm->requestSurface(graphic_role) != 0) {
+ exit(EXIT_FAILURE);
+ }
+ // Create an event callback against an event type. Here a lambda is called when SyncDraw event occurs
+ qwm->set_event_handler(QLibWindowmanager::Event_SyncDraw, [qwm, &graphic_role](json_object *object) {
+ (void)object;
+ qDebug() << "Surface got syncDraw!";
+ qwm->endDraw(graphic_role);
+ });
+
+ // HomeScreen
+ hs->init(port, token.c_str());
+ // Set the event handler for Event_ShowWindow which will activate the surface for windowmanager
+ hs->set_event_handler(LibHomeScreen::Event_ShowWindow, [qwm, &graphic_role](json_object *object){
+ (void)object;
+ qDebug("Surface %s got showWindow\n", graphic_role.toStdString().c_str());
+ qwm->activateWindow(graphic_role);
+ });
+
+ g_cloudproxyclient = new CloudProxyClient();
+ g_cloudproxyclient->init(port, token.c_str());
+
+ static int i_confirm_good{0}, i_confirm_bad{0}, i_recv{0};
+ g_cloudproxyclient->set_event_handler(CloudProxyClient::Event_SendMessageConfirmation, [&window](json_object* object){
+ qDebug("CloudProxyClient::Event_SendMessageConfirmation: object ptr %p", object);
+
+ const char* str = object ? json_object_to_json_string_ext(object, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY) : "<obj_null>";
+ if (!str)
+ str = "<empty>";
+ qDebug("Event_SendMessageConfirmation: %s", str);
+
+ json_object *j_result;
+ if(!json_object_object_get_ex(object, "result", &j_result))
+ {
+ qDebug("Can't read confirmation result");
+ return;
+ }
+
+ int result = (int)json_object_get_boolean(j_result);
+
+ if (result)
+ ++i_confirm_good;
+ else
+ ++i_confirm_bad;
+
+ window->updateStat(i_confirm_good, i_confirm_bad, i_recv, QVariant());
+ qDebug("Application received confirmation result [good: %d, bad: %d]: %d", i_confirm_good, i_confirm_bad, result);
+ });
+ g_cloudproxyclient->set_event_handler(CloudProxyClient::Event_ReceivedMessage, [&window](json_object* object){
+ qDebug("CloudProxyClient::Event_ReceivedMessage: object ptr %p", object);
+
+ const char* str = object ? json_object_to_json_string_ext(object, JSON_C_TO_STRING_SPACED | JSON_C_TO_STRING_PRETTY) : "<obj_null>";
+ if (!str)
+ str = "<empty>";
+ qDebug("Event_SendMessageConfirmation: %s", str);
+
+ json_object *event_data;
+ const char* data_str{nullptr};
+ if(!json_object_object_get_ex(object, "data", &event_data) ||
+ (data_str = json_object_get_string(event_data)) == nullptr)
+ {
+ qDebug("Can't read event data");
+ return;
+ }
+
+ ++i_recv;
+ window->updateStat(i_confirm_good, i_confirm_bad, i_recv, QString(data_str));
+ qDebug("Application received data [count: %d, good: %d, bad %d]: %s", i_recv, i_confirm_good, i_confirm_bad, data_str);
+ });
+
+
+ window->show();
+ qwm->slotActivateWindow();
+ }
+
+ return app.exec();
+}
diff --git a/sample/test-cloud-app/app/mainwindow.cpp b/sample/test-cloud-app/app/mainwindow.cpp
new file mode 100755
index 0000000..355847c
--- /dev/null
+++ b/sample/test-cloud-app/app/mainwindow.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "mainwindow.h"
+#include "ui_mainwindow.h"
+#include <QDebug>
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+
+#include "libcloudproxy.h"
+extern CloudProxyClient* g_cloudproxyclient;
+
+MainWindow::MainWindow(double scale_factor, QWidget *parent) :
+ QMainWindow(parent),
+ ui(new Ui::MainWindow)
+{
+ ui->setupUi(scale_factor, this);
+
+ //AGL style
+ setWindowFlags(Qt::FramelessWindowHint | Qt::WindowSystemMenuHint);
+ this->setStyleSheet(
+ "background-image:url(:/images/AGL_HMI_Blue_Background_NoCar-01.png) 0 0 0 0 stretch stretch; background: transparent;" );
+}
+
+void MainWindow::updateStat(int confirm_good, int confirm_bad, int received, QVariant recvMsg)
+{
+ confirmGood = confirm_good;
+ confirmBad = confirm_bad;
+ receivedCount = received;
+
+ if (recvMsg.isValid())
+ lastReceivedMsg = recvMsg.toString();
+
+ updateStat();
+}
+
+void MainWindow::updateStat()
+{
+ QString str = QString::asprintf("Sent: OK=%d, NOK=%d\nConfirmed: OK=%d, NOK=%d\nReceived=%d\n\n",
+ sendCount, sendErrorCount, confirmGood, confirmBad, receivedCount);
+ str.append("Last sent message:\n");
+ str.append(lastSentMsg);
+ str.append("\n\nLast received message:\n");
+ str.append(lastReceivedMsg);
+ ui->statLabel->setText(str);
+ //QApplication::processEvents();
+}
+
+void MainWindow::sendMsgButtonClick()
+{
+ qDebug() << "MainWindow::sendMegButtonClick()";
+
+ std::string msg = std::string{"{\"app_key\": \"app_value_"} + std::to_string(sendCount + sendErrorCount) + "\"}";
+ int res = g_cloudproxyclient->sendMessage(msg);
+ if (res == 0)
+ ++sendCount;
+ else
+ ++sendErrorCount;
+
+ lastSentMsg = msg.c_str();
+ qDebug() << "cloud sendMessage result: " << res;
+}
+
+
+MainWindow::~MainWindow()
+{
+ delete ui;
+}
diff --git a/sample/test-cloud-app/app/mainwindow.h b/sample/test-cloud-app/app/mainwindow.h
new file mode 100755
index 0000000..ae66729
--- /dev/null
+++ b/sample/test-cloud-app/app/mainwindow.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QMainWindow>
+#include <QVariant>
+#include <memory>
+
+
+namespace Ui {
+ class MainWindow;
+}
+
+class MainWindow : public QMainWindow
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(double scale_factor, QWidget *parent = 0);
+ ~MainWindow();
+
+public slots:
+ void updateStat(int confirm_good, int confirm_bad, int received, QVariant recvMsg);
+
+private slots:
+ void sendMsgButtonClick();
+ void updateStat();
+
+private:
+ Ui::MainWindow *ui;
+ int sendCount{0};
+ int sendErrorCount{0};
+ int confirmGood{0};
+ int confirmBad{0};
+ int receivedCount{0};
+ QString lastSentMsg;
+ QString lastReceivedMsg;
+};
+
+#endif // MAINWINDOW_H
diff --git a/sample/test-cloud-app/app/ui_mainwindow.h b/sample/test-cloud-app/app/ui_mainwindow.h
new file mode 100755
index 0000000..3dac77e
--- /dev/null
+++ b/sample/test-cloud-app/app/ui_mainwindow.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 MERA
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef UI_MAINWINDOW_H
+#define UI_MAINWINDOW_H
+
+#include <QtCore/QVariant>
+#include <QtWidgets/QApplication>
+#include <QtWidgets/QLabel>
+#include <QtWidgets/QMainWindow>
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QLineEdit>
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QFrame>
+#include <QtWidgets/QGroupBox>
+#include <QtWidgets/QRadioButton>
+#include <QtWidgets/QComboBox>
+
+QT_BEGIN_NAMESPACE
+
+class Ui_MainWindow
+{
+public:
+ QWidget *centralWidget{nullptr};
+ QPushButton *sendMsgButton{nullptr};
+ QLabel *appNameLabel{nullptr};
+ QLabel *statLabel{nullptr};
+
+ void setupUi(double scale_factor, QMainWindow *MainWindow)
+ {
+ if (MainWindow->objectName().isEmpty())
+ MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
+ MainWindow->resize(1080*scale_factor, 1400*scale_factor);
+ centralWidget = new QWidget(MainWindow);
+ centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
+
+ //QString style("color: white; font-size: 24px");
+ QString style("color: white");
+
+ sendMsgButton = new QPushButton(centralWidget);
+ sendMsgButton->setObjectName(QString::fromUtf8("sendMsgButton"));
+ sendMsgButton->setGeometry(QRect((540-242/2)*scale_factor, 100*scale_factor, 242*scale_factor, 64*scale_factor));
+ sendMsgButton->setStyleSheet(style);
+
+ appNameLabel = new QLabel(centralWidget);
+ appNameLabel->setObjectName(QString::fromUtf8("label"));
+ appNameLabel->setGeometry(QRect(40*scale_factor, 20*scale_factor, 1000*scale_factor, 32*scale_factor));
+ appNameLabel->setStyleSheet(style);
+
+ statLabel = new QLabel(centralWidget);
+ statLabel->setObjectName(QString::fromUtf8("label"));
+ statLabel->setGeometry(QRect(40*scale_factor, 180*scale_factor, 1000*scale_factor, 420*scale_factor));
+ statLabel->setWordWrap(true);
+ statLabel->setAlignment(Qt::AlignTop);
+ statLabel->setStyleSheet(style);
+
+ MainWindow->setCentralWidget(centralWidget);
+
+ QObject::connect(sendMsgButton, SIGNAL(clicked()), MainWindow, SLOT(sendMsgButtonClick()));
+
+ retranslateUi(MainWindow);
+
+ QMetaObject::connectSlotsByName(MainWindow);
+ } // setupUi
+
+ void retranslateUi(QMainWindow *MainWindow)
+ {
+ MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", nullptr));
+ sendMsgButton->setText(QApplication::translate("MainWindow", "Send message", nullptr));
+ QString name = QString("Test application ") + APP_INSTANCE_NUM;
+ appNameLabel->setText(QApplication::translate("MainWindow", name.toUtf8().constData(), nullptr));
+ } // retranslateUi
+};
+
+namespace Ui {
+ class MainWindow: public Ui_MainWindow {};
+} // namespace Ui
+
+QT_END_NAMESPACE
+
+#endif // UI_MAINWINDOW_H
diff --git a/sample/test-cloud-app/autobuild/agl/autobuild b/sample/test-cloud-app/autobuild/agl/autobuild
new file mode 100755
index 0000000..bbbc13e
--- /dev/null
+++ b/sample/test-cloud-app/autobuild/agl/autobuild
@@ -0,0 +1,110 @@
+#!/usr/bin/make -f
+# Copyright (C) 2015 - 2018 "IoT.bzh"
+# Copyright (C) 2020 Konsulko Group
+# Author "Romain Forlot" <romain.forlot@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+THISFILE := $(lastword $(MAKEFILE_LIST))
+ROOT_DIR := $(abspath $(dir $(THISFILE))/../..)
+
+# Build directories
+# Note that the debug directory is defined in relation to the release
+# directory (BUILD_DIR), this needs to be kept in mind if over-riding
+# it and building that widget types, the specific widget type variable
+# (e.g. BUILD_DIR_DEBUG) may also need to be specified to yield the
+# desired output hierarchy.
+BUILD_DIR = $(ROOT_DIR)/build
+BUILD_DIR_DEBUG = $(abspath $(BUILD_DIR)/../build-debug)
+
+# Output directory variable for use in pattern rules.
+# This is intended for internal use only, hence the explicit override
+# definition.
+override OUTPUT_DIR = $(BUILD_DIR)
+
+# Final install directory for widgets
+DEST = $(OUTPUT_DIR)
+
+# Default build type for release builds
+BUILD_TYPE = release
+
+.PHONY: all help update install distclean
+.PHONY: clean clean-release clean-debug clean-all
+.PHONY: configure configure-release configure-debug
+.PHONY: build build-release build-debug build-all
+.PHONY: package package-release package-debug package-all
+
+help:
+ @echo "List of targets available:"
+ @echo ""
+ @echo "- all"
+ @echo "- help"
+ @echo "- clean"
+ @echo "- distclean"
+ @echo "- configure"
+ @echo "- build: compilation, link and prepare files for package into a widget"
+ @echo "- package: output a widget file '*.wgt'"
+ @echo "- install: install in $(DEST) directory"
+ @echo ""
+ @echo "Usage: ./autobuild/agl/autobuild package DEST=${HOME}/opt"
+ @echo "Don't use your build dir as DEST as wgt file is generated at this location"
+
+all: package-all
+
+# Target specific variable over-rides so static pattern rules can be
+# used for the various type-specific targets.
+
+configure-debug build-debug package-debug clean-debug: OUTPUT_DIR = $(BUILD_DIR_DEBUG)
+configure-debug build-debug package-debug: BUILD_TYPE = debug
+
+clean-release clean-debug:
+ @if [ -d $(OUTPUT_DIR) ]; then \
+ $(MAKE) -C $(OUTPUT_DIR) $(CLEAN_ARGS) clean; \
+ else \
+ echo Nothing to clean; \
+ fi
+
+clean: clean-release
+
+clean-all: clean-release clean-debug
+
+distclean: clean-all
+
+configure-release configure-debug:
+ @mkdir -p $(OUTPUT_DIR)
+ @if [ ! -f $(OUTPUT_DIR)/Makefile ]; then \
+ (cd $(OUTPUT_DIR) && qmake CONFIG+=$(BUILD_TYPE) $(CONFIGURE_ARGS) $(ROOT_DIR)); \
+ fi
+
+configure: configure-release
+
+build-release build-debug: build-%: configure-%
+ @$(MAKE) -C $(OUTPUT_DIR) $(BUILD_ARGS) all
+
+build: build-release
+
+build-all: build-release build-debug
+
+package-release package-debug: package-%: build-%
+ @cp $(OUTPUT_DIR)/package/*.wgt $(OUTPUT_DIR)/
+ @if [ "$(abspath $(DEST))" != "$(abspath $(OUTPUT_DIR))" ]; then \
+ mkdir -p $(DEST) && cp $(OUTPUT_DIR)/*.wgt $(DEST); \
+ fi
+
+
+package: package-release
+
+package-all: package-release package-debug
+
+install: build
+ @$(MAKE) -C $(BUILD_DIR) $(INSTALL_ARGS) install
diff --git a/sample/test-cloud-app/autobuild/linux/autobuild b/sample/test-cloud-app/autobuild/linux/autobuild
new file mode 100755
index 0000000..bbbc13e
--- /dev/null
+++ b/sample/test-cloud-app/autobuild/linux/autobuild
@@ -0,0 +1,110 @@
+#!/usr/bin/make -f
+# Copyright (C) 2015 - 2018 "IoT.bzh"
+# Copyright (C) 2020 Konsulko Group
+# Author "Romain Forlot" <romain.forlot@iot.bzh>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+THISFILE := $(lastword $(MAKEFILE_LIST))
+ROOT_DIR := $(abspath $(dir $(THISFILE))/../..)
+
+# Build directories
+# Note that the debug directory is defined in relation to the release
+# directory (BUILD_DIR), this needs to be kept in mind if over-riding
+# it and building that widget types, the specific widget type variable
+# (e.g. BUILD_DIR_DEBUG) may also need to be specified to yield the
+# desired output hierarchy.
+BUILD_DIR = $(ROOT_DIR)/build
+BUILD_DIR_DEBUG = $(abspath $(BUILD_DIR)/../build-debug)
+
+# Output directory variable for use in pattern rules.
+# This is intended for internal use only, hence the explicit override
+# definition.
+override OUTPUT_DIR = $(BUILD_DIR)
+
+# Final install directory for widgets
+DEST = $(OUTPUT_DIR)
+
+# Default build type for release builds
+BUILD_TYPE = release
+
+.PHONY: all help update install distclean
+.PHONY: clean clean-release clean-debug clean-all
+.PHONY: configure configure-release configure-debug
+.PHONY: build build-release build-debug build-all
+.PHONY: package package-release package-debug package-all
+
+help:
+ @echo "List of targets available:"
+ @echo ""
+ @echo "- all"
+ @echo "- help"
+ @echo "- clean"
+ @echo "- distclean"
+ @echo "- configure"
+ @echo "- build: compilation, link and prepare files for package into a widget"
+ @echo "- package: output a widget file '*.wgt'"
+ @echo "- install: install in $(DEST) directory"
+ @echo ""
+ @echo "Usage: ./autobuild/agl/autobuild package DEST=${HOME}/opt"
+ @echo "Don't use your build dir as DEST as wgt file is generated at this location"
+
+all: package-all
+
+# Target specific variable over-rides so static pattern rules can be
+# used for the various type-specific targets.
+
+configure-debug build-debug package-debug clean-debug: OUTPUT_DIR = $(BUILD_DIR_DEBUG)
+configure-debug build-debug package-debug: BUILD_TYPE = debug
+
+clean-release clean-debug:
+ @if [ -d $(OUTPUT_DIR) ]; then \
+ $(MAKE) -C $(OUTPUT_DIR) $(CLEAN_ARGS) clean; \
+ else \
+ echo Nothing to clean; \
+ fi
+
+clean: clean-release
+
+clean-all: clean-release clean-debug
+
+distclean: clean-all
+
+configure-release configure-debug:
+ @mkdir -p $(OUTPUT_DIR)
+ @if [ ! -f $(OUTPUT_DIR)/Makefile ]; then \
+ (cd $(OUTPUT_DIR) && qmake CONFIG+=$(BUILD_TYPE) $(CONFIGURE_ARGS) $(ROOT_DIR)); \
+ fi
+
+configure: configure-release
+
+build-release build-debug: build-%: configure-%
+ @$(MAKE) -C $(OUTPUT_DIR) $(BUILD_ARGS) all
+
+build: build-release
+
+build-all: build-release build-debug
+
+package-release package-debug: package-%: build-%
+ @cp $(OUTPUT_DIR)/package/*.wgt $(OUTPUT_DIR)/
+ @if [ "$(abspath $(DEST))" != "$(abspath $(OUTPUT_DIR))" ]; then \
+ mkdir -p $(DEST) && cp $(OUTPUT_DIR)/*.wgt $(DEST); \
+ fi
+
+
+package: package-release
+
+package-all: package-release package-debug
+
+install: build
+ @$(MAKE) -C $(BUILD_DIR) $(INSTALL_ARGS) install
diff --git a/sample/test-cloud-app/package/config.xml b/sample/test-cloud-app/package/config.xml
new file mode 100755
index 0000000..7d82afc
--- /dev/null
+++ b/sample/test-cloud-app/package/config.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<widget xmlns="http://www.w3.org/ns/widgets" id="testcloudapp1" version="0.1">
+ <name>CloudApp1</name>
+ <icon src="icon.svg"/>
+ <content src="bin/testcloudapp" type="application/vnd.agl.native"/>
+ <description>Test Cloud App</description>
+ <author>Mera</author>
+ <license>APL 2.0</license>
+ <feature name="urn:AGL:widget:required-api">
+ <param name="homescreen" value="ws"/>
+ <param name="cloudproxy" value="ws"/>
+ </feature>
+ <feature name="urn:AGL:widget:required-permission">
+ <param name="urn:AGL:permission::public:no-htdocs" value="required"/>
+ <param name="urn:AGL:permission::public:display" value="required" />
+ </feature>
+</widget>
diff --git a/sample/test-cloud-app/package/icon.svg b/sample/test-cloud-app/package/icon.svg
new file mode 100755
index 0000000..b9b8e67
--- /dev/null
+++ b/sample/test-cloud-app/package/icon.svg
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:i="&amp;#38;ns_ai;"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ x="0px"
+ y="0px"
+ viewBox="0 0 320 320"
+ style="enable-background:new 0 0 320 320;"
+ xml:space="preserve"
+ id="svg2"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="icon.svg"><metadata
+ id="metadata1292"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs1290" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="2560"
+ inkscape:window-height="1464"
+ id="namedview1288"
+ showgrid="false"
+ inkscape:zoom="4.17193"
+ inkscape:cx="183.76952"
+ inkscape:cy="191.17869"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" /><style
+ type="text/css"
+ id="style4">
+ .st0{display:none;}
+ .st1{display:inline;}
+ .st2{opacity:0.4;fill:url(#SVGID_1_);}
+ .st3{fill:url(#SVGID_2_);}
+ .st4{fill:#FFFFFF;}
+ .st5{font-family:'Roboto-Regular';}
+ .st6{font-size:25px;}
+ .st7{letter-spacing:6;}
+ .st8{fill:url(#SVGID_3_);}
+ .st9{fill:url(#SVGID_4_);}
+ .st10{fill:url(#SVGID_5_);}
+ .st11{fill:url(#SVGID_6_);}
+ .st12{fill:url(#SVGID_7_);}
+ .st13{fill:url(#SVGID_8_);}
+ .st14{fill:url(#SVGID_9_);}
+ .st15{fill:url(#SVGID_10_);}
+ .st16{fill:url(#SVGID_11_);}
+ .st17{fill:url(#SVGID_12_);}
+ .st18{fill:url(#SVGID_13_);}
+ .st19{fill:url(#SVGID_14_);}
+ .st20{fill:url(#SVGID_15_);}
+ .st21{fill:url(#SVGID_16_);}
+ .st22{fill:url(#SVGID_17_);}
+ .st23{fill:url(#SVGID_18_);}
+ .st24{opacity:0.29;}
+ .st25{fill:url(#SVGID_19_);}
+ .st26{fill:url(#SVGID_20_);}
+ .st27{fill:url(#SVGID_21_);}
+ .st28{fill:url(#SVGID_22_);}
+ .st29{fill:url(#SVGID_23_);}
+ .st30{fill:url(#SVGID_24_);}
+ .st31{fill:url(#SVGID_25_);}
+ .st32{fill:url(#SVGID_26_);}
+ .st33{fill:url(#SVGID_27_);}
+ .st34{fill:url(#SVGID_28_);}
+ .st35{fill:url(#SVGID_29_);}
+ .st36{fill:url(#SVGID_30_);}
+ .st37{fill:url(#SVGID_31_);}
+ .st38{fill:url(#SVGID_32_);}
+ .st39{fill:url(#SVGID_33_);}
+ .st40{fill:url(#SVGID_34_);}
+ .st41{fill:url(#SVGID_35_);}
+ .st42{fill:url(#SVGID_36_);}
+ .st43{opacity:0.4;fill:url(#SVGID_37_);}
+ .st44{fill:url(#SVGID_38_);}
+ .st45{fill:url(#SVGID_39_);}
+ .st46{fill:url(#SVGID_40_);}
+ .st47{fill:url(#SVGID_41_);}
+ .st48{fill:url(#SVGID_42_);}
+ .st49{fill:url(#SVGID_43_);}
+ .st50{fill:url(#SVGID_44_);}
+ .st51{display:inline;opacity:0.29;}
+ .st52{display:inline;fill:url(#SVGID_45_);}
+ .st53{display:inline;fill:url(#SVGID_46_);}
+ .st54{display:inline;fill:#FFFFFF;}
+ .st55{display:inline;fill:url(#SVGID_47_);}
+ .st56{display:inline;fill:url(#SVGID_48_);}
+ .st57{display:inline;fill:url(#SVGID_49_);}
+ .st58{display:inline;fill:url(#SVGID_50_);}
+ .st59{display:inline;fill:url(#SVGID_51_);}
+ .st60{display:inline;fill:url(#SVGID_52_);}
+ .st61{opacity:0.4;fill:url(#SVGID_53_);}
+ .st62{fill:url(#SVGID_54_);}
+ .st63{fill:url(#SVGID_55_);}
+ .st64{fill:url(#SVGID_56_);}
+ .st65{fill:url(#SVGID_57_);}
+ .st66{fill:url(#SVGID_58_);}
+ .st67{opacity:0.4;fill:url(#SVGID_59_);}
+ .st68{fill:url(#SVGID_60_);}
+ .st69{fill:url(#SVGID_61_);}
+ .st70{fill:url(#SVGID_62_);}
+ .st71{fill:url(#SVGID_63_);}
+ .st72{fill:url(#SVGID_64_);}
+ .st73{fill:url(#SVGID_65_);}
+ .st74{fill:url(#SVGID_66_);}
+ .st75{fill:url(#SVGID_67_);}
+ .st76{fill:url(#SVGID_68_);}
+ .st77{fill:url(#SVGID_69_);}
+ .st78{fill:url(#SVGID_70_);}
+ .st79{fill:url(#SVGID_71_);}
+ .st80{fill:url(#SVGID_72_);}
+ .st81{fill:url(#SVGID_73_);}
+ .st82{fill:url(#SVGID_74_);}
+ .st83{fill:url(#SVGID_75_);}
+ .st84{fill:url(#SVGID_76_);}
+ .st85{fill:url(#SVGID_77_);}
+ .st86{fill:url(#SVGID_78_);}
+ .st87{fill:url(#SVGID_79_);}
+ .st88{fill:url(#SVGID_80_);}
+ .st89{fill:url(#SVGID_81_);}
+ .st90{fill:url(#SVGID_82_);}
+ .st91{fill:url(#SVGID_83_);}
+ .st92{fill:url(#SVGID_84_);}
+ .st93{fill:url(#SVGID_85_);}
+ .st94{fill:url(#SVGID_86_);}
+ .st95{opacity:0.4;fill:url(#SVGID_87_);}
+ .st96{fill:url(#SVGID_88_);}
+ .st97{fill:url(#SVGID_89_);}
+ .st98{fill:url(#SVGID_90_);}
+ .st99{fill:url(#SVGID_91_);}
+ .st100{fill:url(#SVGID_92_);}
+ .st101{fill:url(#SVGID_93_);}
+ .st102{fill:url(#SVGID_94_);}
+ .st103{opacity:0.4;fill:url(#SVGID_95_);}
+ .st104{fill:url(#SVGID_96_);}
+ .st105{fill:url(#SVGID_97_);}
+ .st106{fill:url(#SVGID_98_);}
+ .st107{fill:url(#SVGID_99_);}
+ .st108{fill:url(#SVGID_100_);}
+ .st109{fill:url(#SVGID_101_);}
+ .st110{display:inline;fill:url(#SVGID_102_);}
+ .st111{display:inline;fill:url(#SVGID_103_);}
+ .st112{fill:url(#SVGID_104_);}
+ .st113{fill:url(#SVGID_105_);}
+ .st114{fill:url(#SVGID_106_);}
+ .st115{fill:url(#SVGID_107_);}
+ .st116{fill:url(#SVGID_108_);}
+ .st117{opacity:0.4;fill:url(#SVGID_109_);}
+ .st118{fill:url(#SVGID_110_);}
+ .st119{fill:url(#SVGID_111_);}
+ .st120{fill:url(#SVGID_112_);}
+ .st121{fill:url(#SVGID_113_);}
+ .st122{fill:url(#SVGID_114_);}
+ .st123{opacity:0.4;fill:url(#SVGID_115_);}
+ .st124{fill:url(#SVGID_116_);}
+ .st125{fill:url(#SVGID_117_);}
+ .st126{fill:url(#SVGID_118_);}
+ .st127{display:inline;fill:url(#SVGID_119_);}
+ .st128{display:inline;fill:url(#SVGID_120_);}
+ .st129{fill:url(#SVGID_121_);}
+ .st130{fill:url(#SVGID_122_);}
+</style><switch
+ id="switch6"><g
+ i:extraneous="self"
+ id="g8"><g
+ id="Multimedia_Inactive_copy"><circle
+ class="st24"
+ cx="159.7"
+ cy="133.4"
+ r="101.9"
+ id="circle884" /><linearGradient
+ id="SVGID_91_"
+ gradientUnits="userSpaceOnUse"
+ x1="115.9317"
+ y1="254.1836"
+ x2="256.3852"
+ y2="-133.5267"><stop
+ offset="0"
+ style="stop-color:#8BC53F"
+ id="stop887" /><stop
+ offset="2.015080e-02"
+ style="stop-color:#7CCB56;stop-opacity:0.9678"
+ id="stop889" /><stop
+ offset="6.089833e-02"
+ style="stop-color:#62D67D;stop-opacity:0.9028"
+ id="stop891" /><stop
+ offset="0.1057"
+ style="stop-color:#4BDFA0;stop-opacity:0.8312"
+ id="stop893" /><stop
+ offset="0.1543"
+ style="stop-color:#38E7BE;stop-opacity:0.7537"
+ id="stop895" /><stop
+ offset="0.2077"
+ style="stop-color:#28EED6;stop-opacity:0.6684"
+ id="stop897" /><stop
+ offset="0.2681"
+ style="stop-color:#1CF3E8;stop-opacity:0.572"
+ id="stop899" /><stop
+ offset="0.3394"
+ style="stop-color:#13F6F5;stop-opacity:0.4581"
+ id="stop901" /><stop
+ offset="0.4323"
+ style="stop-color:#0EF8FD;stop-opacity:0.3098"
+ id="stop903" /><stop
+ offset="0.6264"
+ style="stop-color:#0DF9FF;stop-opacity:0"
+ id="stop905" /></linearGradient><circle
+ class="st99"
+ cx="159.7"
+ cy="133.4"
+ r="101.9"
+ id="circle907" /><linearGradient
+ id="SVGID_92_"
+ gradientUnits="userSpaceOnUse"
+ x1="4.0481"
+ y1="287.9492"
+ x2="320.4859"
+ y2="-15.4029"
+ gradientTransform="matrix(1 5.464556e-03 -5.464556e-03 1 -2.0192 -3.0212)"><stop
+ offset="0"
+ style="stop-color:#59FF7F"
+ id="stop910" /><stop
+ offset="1"
+ style="stop-color:#6BFBFF"
+ id="stop912" /></linearGradient><path
+ class="st100"
+ d="M160,238.8c-0.2,0-0.4,0-0.6,0c-58-0.3-104.9-47.7-104.6-105.7C55.2,75.3,102.3,28.5,160,28.5 c0.2,0,0.4,0,0.6,0c58,0.3,104.9,47.7,104.6,105.7l0,0C264.8,192,217.7,238.8,160,238.8z M160,32.2 c-55.7,0-101.2,45.2-101.5,100.9c-0.3,55.9,45,101.7,100.9,102c0.2,0,0.4,0,0.6,0c55.7,0,101.2-45.2,101.5-100.9 c0.3-55.9-45-101.7-100.9-102C160.4,32.2,160.2,32.2,160,32.2z"
+ id="path914" /><g
+ id="g916"><text
+ transform="matrix(1 0 0 1 53.5841 284.7119)"
+ class="st4 st5 st6 st7"
+ id="text918">VIDEOPLAYER
+</text>
+<linearGradient
+ id="SVGID_94_"
+ gradientUnits="userSpaceOnUse"
+ x1="145.3286"
+ y1="203.8951"
+ x2="191.6285"
+ y2="70.3637"><stop
+ offset="0"
+ style="stop-color:#59FF7F"
+ id="stop928" /><stop
+ offset="1"
+ style="stop-color:#6BFBFF"
+ id="stop930" /></linearGradient><polygon
+ class="st102"
+ points="125,75 125,200 225,137.5 "
+ id="polygon932"
+ style="fill:url(#SVGID_94_)" /></g></g></g></switch></svg> \ No newline at end of file
diff --git a/sample/test-cloud-app/package/package.pro b/sample/test-cloud-app/package/package.pro
new file mode 100755
index 0000000..c8af452
--- /dev/null
+++ b/sample/test-cloud-app/package/package.pro
@@ -0,0 +1,28 @@
+
+DISTFILES = icon.svg config.xml
+
+copy_icon.target = $$OUT_PWD/root/icon.svg
+copy_icon.depends = $$_PRO_FILE_PWD_/icon.svg
+copy_icon.commands = $(COPY_FILE) \"$$replace(copy_icon.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_icon.target, /, $$QMAKE_DIR_SEP)\"
+QMAKE_EXTRA_TARGETS += copy_icon
+PRE_TARGETDEPS += $$copy_icon.target
+
+copy_config.target = $$OUT_PWD/root/config.xml
+copy_config.depends = $$_PRO_FILE_PWD_/config.xml
+copy_config.commands = $(COPY_FILE) \"$$replace(copy_config.depends, /, $$QMAKE_DIR_SEP)\" \"$$replace(copy_config.target, /, $$QMAKE_DIR_SEP)\"
+QMAKE_EXTRA_TARGETS += copy_config
+PRE_TARGETDEPS += $$copy_config.target
+
+WGT_TYPE =
+CONFIG(debug, debug|release) {
+ WGT_TYPE = -debug
+}
+
+wgt.target = package
+wgt.commands = wgtpkg-pack -f -o testcloudapp$${WGT_TYPE}.wgt root
+
+QMAKE_EXTRA_TARGETS += wgt
+
+deploy.files = testcloudapp.wgt
+deploy.path = /usr/AGL/apps/autoinstall
+INSTALLS += deploy
diff --git a/sample/test-cloud-app/testcloudapp.pro b/sample/test-cloud-app/testcloudapp.pro
new file mode 100755
index 0000000..579a952
--- /dev/null
+++ b/sample/test-cloud-app/testcloudapp.pro
@@ -0,0 +1,3 @@
+TEMPLATE = subdirs
+SUBDIRS = app package
+package.depends += app