summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorScott Murray <scott.murray@konsulko.com>2020-01-15 14:22:17 -0500
committerScott Murray <scott.murray@konsulko.com>2020-01-16 14:23:13 -0500
commitcd5c8fee6f24d3704c3fc7d94b36d86c07c0369f (patch)
treeaee51b644cd7fd7a2e9c0464474a78e6d1cd156f
parent68cb7fec30353f3aaffb06c32f172effe6262874 (diff)
Add initial voice-capabilities binding support
Add support for subscribing to and using the guimetadata events from the vshl-capabilities binding. A GuiMetadata class is used to wrap things as it is likely that users of the other voice capabilities would not overlap if e.g. navigation event support is later added. At the moment, only the BodyTemplate1, BodyTemplate2, and WeatherTemplate guimetadata types are handled, and there is room for significant improvement in the Qt model exposed, which is somewhat crude with respect to image URL handling. As well, the weather template handling does not expose the full forecast, a full implementation of that would require adding an actual model that maps to a list view rather than a simple QObject. Bug-AGL: SPEC-3110 Signed-off-by: Scott Murray <scott.murray@konsulko.com> Change-Id: I33fc2440ebdc2a4a2de79ff0a49acbc422c47da2
-rw-r--r--CMakeLists.txt1
-rw-r--r--message.h1
-rw-r--r--messageengine.cpp9
-rw-r--r--voice-capabilities/CMakeLists.txt2
-rw-r--r--voice-capabilities/guimetadata.cpp344
-rw-r--r--voice-capabilities/guimetadata.h174
-rw-r--r--voice-capabilities/guimetadatamessage.cpp30
-rw-r--r--voice-capabilities/guimetadatamessage.h38
8 files changed, 598 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2f576e9..bf1cba4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -57,6 +57,7 @@ set (SUBDIRS
signal-composer
telephony
voice
+ voice-capabilities
weather)
add_headers(message.h messageengine.h responsemessage.h)
diff --git a/message.h b/message.h
index df640ec..87cd461 100644
--- a/message.h
+++ b/message.h
@@ -44,6 +44,7 @@ enum MessageType {
NavigationEventMessage,
VoiceEventMessage,
SignalComposerEventMessage,
+ GuiMetadataCapabilityEventMessage,
};
class Message : public QObject
diff --git a/messageengine.cpp b/messageengine.cpp
index d2644e8..115dde7 100644
--- a/messageengine.cpp
+++ b/messageengine.cpp
@@ -17,6 +17,7 @@
#include "message.h"
#include "messageengine.h"
#include "bluetoothmessage.h"
+#include "guimetadatamessage.h"
#include "mapmessage.h"
#include "mediaplayermessage.h"
#include "navigationmessage.h"
@@ -24,10 +25,10 @@
#include "pbapmessage.h"
#include "radiomessage.h"
#include "responsemessage.h"
+#include "signalcomposermessage.h"
#include "telephonymessage.h"
#include "weathermessage.h"
#include "voicemessage.h"
-#include "signalcomposermessage.h"
#include <QJsonArray>
@@ -143,6 +144,12 @@ void MessageEngine::onTextMessageReceived(QString jsonStr)
} else if (api == "vshl-core" ) {
message = new VoiceMessage;
type = VoiceEventMessage;
+ } else if (api == "vshl-capabilities" ) {
+ // NOTE: Will need to look at event name to differentiate
+ // capabilities if more support (e.g. navigation or
+ // local media control) is added.
+ message = new GuiMetadataCapabilityMessage;
+ type = GuiMetadataCapabilityEventMessage;
} else if (api == "signal-composer") {
message = new SignalComposerMessage;
type = SignalComposerEventMessage;
diff --git a/voice-capabilities/CMakeLists.txt b/voice-capabilities/CMakeLists.txt
new file mode 100644
index 0000000..e1a6089
--- /dev/null
+++ b/voice-capabilities/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_headers(guimetadata.h guimetadatamessage.h)
+add_sources(guimetadata.cpp guimetadatamessage.cpp)
diff --git a/voice-capabilities/guimetadata.cpp b/voice-capabilities/guimetadata.cpp
new file mode 100644
index 0000000..2ab86c5
--- /dev/null
+++ b/voice-capabilities/guimetadata.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2020 Konsulko Group
+ *
+ * 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 "message.h"
+#include "messageengine.h"
+#include "guimetadata.h"
+#include "guimetadatamessage.h"
+
+#include <QJsonArray>
+
+GuiMetadata::GuiMetadata(QUrl &url, QQmlContext *context, QObject * parent) :
+ QObject(parent),
+ m_mloop(nullptr)
+{
+ m_mloop = new MessageEngine(url);
+ m_context = context;
+ QObject::connect(m_mloop, &MessageEngine::connected, this, &GuiMetadata::onConnected);
+ QObject::connect(m_mloop, &MessageEngine::disconnected, this, &GuiMetadata::onDisconnected);
+ QObject::connect(m_mloop, &MessageEngine::messageReceived, this, &GuiMetadata::onMessageReceived);
+}
+
+GuiMetadata::~GuiMetadata()
+{
+ delete m_mloop;
+}
+
+// Qt UI Context
+
+void GuiMetadata::clearMetadata()
+{
+ m_type = "";
+ m_title = "";
+ m_subtitle = "";
+
+ m_bodyText = "";
+ m_bodyImageSmallUrl = "";
+ m_bodyImageMediumUrl = "";
+ m_bodyImageLargeUrl = "";
+
+ m_weatherCurrentTemperature = "";
+ m_weatherCurrentWeatherIconSmallUrl = "";
+ m_weatherCurrentWeatherIconSmallDarkBgUrl = "";
+ m_weatherCurrentWeatherIconMediumUrl = "";
+ m_weatherCurrentWeatherIconMediumDarkBgUrl = "";
+ m_weatherCurrentWeatherIconLargeUrl = "";
+ m_weatherCurrentWeatherIconLargeDarkBgUrl = "";
+
+ m_weatherLowTemperature = "";
+ m_weatherLowTemperatureArrowSmallUrl = "";
+ m_weatherLowTemperatureArrowSmallDarkBgUrl = "";
+ m_weatherLowTemperatureArrowMediumUrl = "";
+ m_weatherLowTemperatureArrowMediumDarkBgUrl = "";
+ m_weatherLowTemperatureArrowLargeUrl = "";
+ m_weatherLowTemperatureArrowLargeDarkBgUrl = "";
+
+ m_weatherHighTemperature = "";
+ m_weatherHighTemperatureArrowSmallUrl = "";
+ m_weatherHighTemperatureArrowSmallDarkBgUrl = "";
+ m_weatherHighTemperatureArrowMediumUrl = "";
+ m_weatherHighTemperatureArrowMediumDarkBgUrl = "";
+ m_weatherHighTemperatureArrowLargeUrl = "";
+ m_weatherHighTemperatureArrowLargeDarkBgUrl = "";
+}
+
+bool GuiMetadata::parseImageMetadata(QJsonObject &imageObj,
+ QUrl &smallUrl, QUrl &mediumUrl, QUrl &largeUrl,
+ QUrl *pSmallDarkBgUrl, QUrl *pMediumDarkBgUrl, QUrl *pLargeDarkBgUrl)
+{
+ if(!(imageObj.contains("sources") && imageObj["sources"].isArray())) {
+ // error
+ qWarning() << "Could not find image.sources parameter!";
+ return false;
+ }
+ QJsonArray sourcesObj = imageObj["sources"].toArray();
+ bool found = false;
+ for(QJsonArray::iterator it = sourcesObj.begin(); it != sourcesObj.end(); it++) {
+ if(!it->isObject()) {
+ // unexpected, skip
+ continue;
+ }
+ QJsonObject sourceObj = it->toObject();
+ if(!(sourceObj.contains("url") && sourceObj["url"].isString())) {
+ // error
+ qWarning() << "Missing image.sources.url parameter!";
+ continue;
+ }
+ QString url = sourceObj["url"].toString();
+ QString darkBackgroundUrl = "";
+ if(sourceObj.contains("darkBackgroundUrl") && sourceObj["darkBackgroundUrl"].isString()) {
+ darkBackgroundUrl = sourceObj["darkBackgroundUrl"].toString();
+ }
+ if(sourceObj.contains("size") && sourceObj["size"].isString()) {
+ QString size = sourceObj["size"].toString();
+ if(size == "SMALL") {
+ smallUrl = url;
+ if(pSmallDarkBgUrl)
+ pSmallDarkBgUrl->setUrl(darkBackgroundUrl);
+ found = true;
+ } else if(size == "MEDIUM") {
+ mediumUrl = url;
+ if(pMediumDarkBgUrl)
+ pMediumDarkBgUrl->setUrl(darkBackgroundUrl);
+ found = true;
+ } else if(size == "LARGE") {
+ largeUrl = url;
+ if(pLargeDarkBgUrl)
+ pLargeDarkBgUrl->setUrl(darkBackgroundUrl);
+ found = true;
+ }
+ // else ignore (X-SMALL, X-LARGE)
+ }
+ // FIXME: Should handle image sources w/o size fields,
+ // parse width/height if present
+ }
+ return found;
+}
+
+bool GuiMetadata::updateMetadata(QJsonObject data)
+{
+ if(!data.contains("type"))
+ return false;
+
+ clearMetadata();
+
+ QString type = data["type"].toString();
+ if(!(type == "BodyTemplate1" ||
+ type == "BodyTemplate2" ||
+ type == "WeatherTemplate")) {
+ // Show unsupported type message
+ m_type = "Unsupported";
+ return true;
+ }
+ m_type = type;
+
+ // All template types have title
+ if(data.contains("title") && data["title"].isObject()) {
+ QJsonObject titleObj = data["title"].toObject();
+ if(titleObj.contains("mainTitle")) {
+ m_title = titleObj["mainTitle"].toString();
+ } else {
+ qWarning() << "Could not find title.mainTitle parameter!";
+ return false;
+ }
+ // subTitle is apparently optional
+ if(titleObj.contains("subTitle"))
+ m_subtitle = titleObj["subTitle"].toString();
+ } else {
+ // error
+ qWarning() << "Could not find title parameter!";
+ return false;
+ }
+
+ if(type == "BodyTemplate1" || type == "BodyTemplate2")
+ return updateBodyMetadata(data);
+ else
+ return updateWeatherMetadata(data);
+}
+
+bool GuiMetadata::updateBodyMetadata(QJsonObject &data)
+{
+ if(!data.contains("type"))
+ return false;
+
+ QString type = data["type"].toString();
+ if(!(type == "BodyTemplate1" || type == "BodyTemplate2"))
+ return false;
+
+ // BodyTemplate1/2 have text field
+ if(data.contains("textField")) {
+ m_bodyText = data["textField"].toString();
+ } else {
+ // error
+ qWarning() << "Could not find textField parameter!";
+ return false;
+ }
+
+ // BodyTemplate2 has image
+ if(type == "BodyTemplate2") {
+ if(!(data.contains("image") && data["image"].isObject())) {
+ // error
+ qWarning() << "Could not find image parameter!";
+ return false;
+ }
+ QJsonObject imageObj = data["image"].toObject();
+ if(!parseImageMetadata(imageObj,
+ m_bodyImageSmallUrl,
+ m_bodyImageMediumUrl,
+ m_bodyImageLargeUrl)) {
+ qWarning() << "Could not parse image parameter!";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool GuiMetadata::updateWeatherMetadata(QJsonObject &data)
+{
+ if(!data.contains("type"))
+ return false;
+
+ QString type = data["type"].toString();
+ if(type != "WeatherTemplate")
+ return false;
+
+ if(data.contains("currentWeather")) {
+ m_weatherCurrentTemperature = data["currentWeather"].toString();
+ } else {
+ // error
+ qWarning() << "Could not find currentWeather parameter!";
+ return false;
+ }
+
+ if(!(data.contains("currentWeatherIcon") && data["currentWeatherIcon"].isObject())) {
+ // error
+ qWarning() << "Could not find currentWeatherIcon parameter!";
+ return false;
+ }
+ QJsonObject imageObj = data["currentWeatherIcon"].toObject();
+ if(!parseImageMetadata(imageObj,
+ m_weatherCurrentWeatherIconSmallUrl,
+ m_weatherCurrentWeatherIconMediumUrl,
+ m_weatherCurrentWeatherIconLargeUrl,
+ &m_weatherCurrentWeatherIconSmallDarkBgUrl,
+ &m_weatherCurrentWeatherIconMediumDarkBgUrl,
+ &m_weatherCurrentWeatherIconLargeDarkBgUrl)) {
+ qWarning() << "Could not parse currentWeatherIcon.image parameter!";
+ return false;
+ }
+
+ if(!(data.contains("lowTemperature") && data["lowTemperature"].isObject())) {
+ // error
+ qWarning() << "Could not find lowTemperature parameter!";
+ return false;
+ }
+ QJsonObject tempObj = data["lowTemperature"].toObject();
+ if(!(tempObj.contains("value") && tempObj["value"].isString())) {
+ // error
+ qWarning() << "Could not find lowTemperature.value parameter!";
+ return false;
+ }
+ m_weatherLowTemperature = tempObj["value"].toString();
+
+ if(!(tempObj.contains("arrow") && tempObj["arrow"].isObject())) {
+ // error
+ qWarning() << "Could not find lowTemperature.arrow parameter!";
+ return false;
+ }
+ imageObj = tempObj["arrow"].toObject();
+ if(!parseImageMetadata(imageObj,
+ m_weatherLowTemperatureArrowSmallUrl,
+ m_weatherLowTemperatureArrowMediumUrl,
+ m_weatherLowTemperatureArrowLargeUrl,
+ &m_weatherLowTemperatureArrowSmallDarkBgUrl,
+ &m_weatherLowTemperatureArrowMediumDarkBgUrl,
+ &m_weatherLowTemperatureArrowLargeDarkBgUrl)) {
+ qWarning() << "Could not parse lowTemperature.arrow parameter!";
+ return false;
+ }
+
+ if(!(data.contains("highTemperature") && data["highTemperature"].isObject())) {
+ // error
+ qWarning() << "Could not find highTemperature parameter!";
+ return false;
+ }
+ tempObj = data["highTemperature"].toObject();
+ if(!(tempObj.contains("value") && tempObj["value"].isString())) {
+ // error
+ qWarning() << "Could not find highTemperature.value parameter!";
+ return false;
+ }
+ m_weatherHighTemperature = tempObj["value"].toString();
+
+ if(!(tempObj.contains("arrow") && tempObj["arrow"].isObject())) {
+ // error
+ qWarning() << "Could not find highTemperature.arrow parameter!";
+ return false;
+ }
+ imageObj = tempObj["arrow"].toObject();
+ if(!parseImageMetadata(imageObj,
+ m_weatherHighTemperatureArrowSmallUrl,
+ m_weatherHighTemperatureArrowMediumUrl,
+ m_weatherHighTemperatureArrowLargeUrl,
+ &m_weatherHighTemperatureArrowSmallDarkBgUrl,
+ &m_weatherHighTemperatureArrowMediumDarkBgUrl,
+ &m_weatherHighTemperatureArrowLargeDarkBgUrl)) {
+ qWarning() << "Could not parse highTemperature.arrow parameter!";
+ return false;
+ }
+
+ return true;
+
+}
+
+void GuiMetadata::onConnected()
+{
+ QStringListIterator eventIterator(events);
+ GuiMetadataCapabilityMessage *tmsg;
+
+ tmsg = new GuiMetadataCapabilityMessage();
+ QJsonObject parameter;
+ QJsonArray actions;
+ while (eventIterator.hasNext()) {
+ actions.append(QJsonValue(eventIterator.next()));
+ }
+ parameter.insert("actions", actions);
+ tmsg->createRequest("guimetadata/subscribe", parameter);
+ m_mloop->sendMessage(tmsg);
+ delete tmsg;
+}
+
+void GuiMetadata::onDisconnected()
+{
+ // vshl-capabilities currently has no unsubscribe verb...
+}
+
+void GuiMetadata::onMessageReceived(MessageType type, Message *message)
+{
+ if (type == GuiMetadataCapabilityEventMessage) {
+ GuiMetadataCapabilityMessage *tmsg = qobject_cast<GuiMetadataCapabilityMessage*>(message);
+ if (tmsg->isEvent()) {
+ if (tmsg->isGuiMetadataRenderTemplateEvent()) {
+ if(updateMetadata(tmsg->eventData()))
+ emit renderTemplate();
+ } else if (tmsg->isGuiMetadataClearTemplateEvent()) {
+ emit clearTemplate();
+ }
+ }
+ }
+ message->deleteLater();
+}
diff --git a/voice-capabilities/guimetadata.h b/voice-capabilities/guimetadata.h
new file mode 100644
index 0000000..c4a551f
--- /dev/null
+++ b/voice-capabilities/guimetadata.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2020 Konsulko Group
+ *
+ * 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 GUIMETADATA_H
+#define GUIMETADATA_H
+
+#include <QDebug>
+#include <QObject>
+
+#include <QtQml/QQmlContext>
+#include "messageengine.h"
+
+class GuiMetadata : public QObject
+{
+ Q_OBJECT
+
+ // Common to all template types
+ Q_PROPERTY(QString type READ type)
+ Q_PROPERTY(QString title READ title)
+ Q_PROPERTY(QString subtitle READ subtitle)
+
+ // BodyTemplate1/2
+ Q_PROPERTY(QString bodyText READ bodyText)
+
+ // BodyTemplate2
+ Q_PROPERTY(QUrl bodyImageSmallUrl READ bodyImageSmallUrl)
+ Q_PROPERTY(QUrl bodyImageMediumUrl READ bodyImageMediumUrl)
+ Q_PROPERTY(QUrl bodyImageLargeUrl READ bodyImageLargeUrl)
+
+ // WeatherTemplate
+ Q_PROPERTY(QString weatherCurrentTemperature READ weatherCurrentTemperature)
+ Q_PROPERTY(QUrl weatherCurrentWeatherIconSmallUrl READ weatherCurrentWeatherIconSmallUrl)
+ Q_PROPERTY(QUrl weatherCurrentWeatherIconSmallDarkBgUrl READ weatherCurrentWeatherIconSmallDarkBgUrl)
+ Q_PROPERTY(QUrl weatherCurrentWeatherIconMediumUrl READ weatherCurrentWeatherIconMediumUrl)
+ Q_PROPERTY(QUrl weatherCurrentWeatherIconMediumDarkBgUrl READ weatherCurrentWeatherIconMediumDarkBgUrl)
+ Q_PROPERTY(QUrl weatherCurrentWeatherIconLargeUrl READ weatherCurrentWeatherIconLargeUrl)
+ Q_PROPERTY(QUrl weatherCurrentWeatherIconLargeDarkBgUrl READ weatherCurrentWeatherIconLargeDarkBgUrl)
+
+ Q_PROPERTY(QString weatherLowTemperature READ weatherLowTemperature)
+ Q_PROPERTY(QUrl weatherLowTemperatureArrowSmallUrl READ weatherLowTemperatureArrowSmallUrl)
+ Q_PROPERTY(QUrl weatherLowTemperatureArrowSmallDarkBgUrl READ weatherLowTemperatureArrowSmallDarkBgUrl)
+ Q_PROPERTY(QUrl weatherLowTemperatureArrowMediumUrl READ weatherLowTemperatureArrowMediumUrl)
+ Q_PROPERTY(QUrl weatherLowTemperatureArrowMediumDarkBgUrl READ weatherLowTemperatureArrowMediumDarkBgUrl)
+ Q_PROPERTY(QUrl weatherLowTemperatureArrowLargeUrl READ weatherLowTemperatureArrowLargeUrl)
+ Q_PROPERTY(QUrl weatherLowTemperatureArrowLargeDarkBgUrl READ weatherLowTemperatureArrowLargeDarkBgUrl)
+
+ Q_PROPERTY(QString weatherHighTemperature READ weatherHighTemperature)
+ Q_PROPERTY(QUrl weatherHighTemperatureArrowSmallUrl READ weatherHighTemperatureArrowSmallUrl)
+ Q_PROPERTY(QUrl weatherHighTemperatureArrowSmallDarkBgUrl READ weatherHighTemperatureArrowSmallDarkBgUrl)
+ Q_PROPERTY(QUrl weatherHighTemperatureArrowMediumUrl READ weatherHighTemperatureArrowMediumUrl)
+ Q_PROPERTY(QUrl weatherHighTemperatureArrowMediumDarkBgUrl READ weatherHighTemperatureArrowMediumDarkBgUrl)
+ Q_PROPERTY(QUrl weatherHighTemperatureArrowLargeUrl READ weatherHighTemperatureArrowLargeUrl)
+ Q_PROPERTY(QUrl weatherHighTemperatureArrowLargeDarkBgUrl READ weatherHighTemperatureArrowLargeDarkBgUrl)
+ // weatherForecast array ignored for now
+
+public:
+ explicit GuiMetadata(QUrl &url, QQmlContext *context, QObject * parent = Q_NULLPTR);
+ virtual ~GuiMetadata();
+
+ QString type() { return m_type; }
+ QString title() { return m_title; }
+ QString subtitle() { return m_subtitle; }
+
+ // BodyTemplate1/2
+ QString bodyText() { return m_bodyText; }
+
+ // BodyTemplate2
+ QUrl bodyImageSmallUrl() { return m_bodyImageSmallUrl; }
+ QUrl bodyImageMediumUrl() { return m_bodyImageMediumUrl; }
+ QUrl bodyImageLargeUrl() { return m_bodyImageLargeUrl; }
+
+ // WeatherTemplate
+ QString weatherCurrentTemperature() { return m_weatherCurrentTemperature; }
+ QUrl weatherCurrentWeatherIconSmallUrl() { return m_weatherCurrentWeatherIconSmallUrl; }
+ QUrl weatherCurrentWeatherIconSmallDarkBgUrl() { return m_weatherCurrentWeatherIconSmallDarkBgUrl; }
+ QUrl weatherCurrentWeatherIconMediumUrl() { return m_weatherCurrentWeatherIconMediumUrl; }
+ QUrl weatherCurrentWeatherIconMediumDarkBgUrl() { return m_weatherCurrentWeatherIconMediumDarkBgUrl; }
+ QUrl weatherCurrentWeatherIconLargeUrl() { return m_weatherCurrentWeatherIconLargeUrl; }
+ QUrl weatherCurrentWeatherIconLargeDarkBgUrl() { return m_weatherCurrentWeatherIconLargeDarkBgUrl; }
+
+ QString weatherLowTemperature() { return m_weatherLowTemperature; }
+ QUrl weatherLowTemperatureArrowSmallUrl() { return m_weatherLowTemperatureArrowSmallUrl; }
+ QUrl weatherLowTemperatureArrowSmallDarkBgUrl() { return m_weatherLowTemperatureArrowSmallDarkBgUrl; }
+ QUrl weatherLowTemperatureArrowMediumUrl() { return m_weatherLowTemperatureArrowMediumUrl; }
+ QUrl weatherLowTemperatureArrowMediumDarkBgUrl() { return m_weatherLowTemperatureArrowMediumDarkBgUrl; }
+ QUrl weatherLowTemperatureArrowLargeUrl() { return m_weatherLowTemperatureArrowLargeUrl; }
+ QUrl weatherLowTemperatureArrowLargeDarkBgUrl() { return m_weatherLowTemperatureArrowLargeDarkBgUrl; }
+
+ QString weatherHighTemperature() { return m_weatherHighTemperature; }
+ QUrl weatherHighTemperatureArrowSmallUrl() { return m_weatherHighTemperatureArrowSmallUrl; }
+ QUrl weatherHighTemperatureArrowSmallDarkBgUrl() { return m_weatherHighTemperatureArrowSmallDarkBgUrl; }
+ QUrl weatherHighTemperatureArrowMediumUrl() { return m_weatherHighTemperatureArrowMediumUrl; }
+ QUrl weatherHighTemperatureArrowMediumDarkBgUrl() { return m_weatherHighTemperatureArrowMediumDarkBgUrl; }
+ QUrl weatherHighTemperatureArrowLargeUrl() { return m_weatherHighTemperatureArrowLargeUrl; }
+ QUrl weatherHighTemperatureArrowLargeDarkBgUrl() { return m_weatherHighTemperatureArrowLargeDarkBgUrl; }
+
+signals:
+ void renderTemplate();
+ void clearTemplate();
+
+private:
+ MessageEngine *m_mloop;
+ QQmlContext *m_context;
+
+ void clearMetadata();
+ bool parseImageMetadata(QJsonObject &imageObj,
+ QUrl &smallUrl, QUrl &mediumUrl, QUrl &largeUrl,
+ QUrl *pSmallDarkBgUrl = NULL, QUrl *pMediumDarkBgUrl = NULL, QUrl *pLargeDarkBgUrl = NULL);
+
+ bool updateMetadata(QJsonObject data);
+ bool updateBodyMetadata(QJsonObject &data);
+ bool updateWeatherMetadata(QJsonObject &data);
+
+ void onConnected();
+ void onDisconnected();
+ void onMessageReceived(MessageType, Message*);
+
+ const QStringList events {
+ "render_template",
+ "clear_template",
+ };
+
+ QString m_type = "";
+ QString m_title = "";
+ QString m_subtitle = "";
+
+ // BodyTemplate1/2
+ QString m_bodyText = "";
+
+ // BodyTemplate2
+ QUrl m_bodyImageSmallUrl = QString("");
+ QUrl m_bodyImageMediumUrl = QString("");
+ QUrl m_bodyImageLargeUrl = QString("");
+
+ // WeatherTemplate
+ QString m_weatherCurrentTemperature = "";
+ QUrl m_weatherCurrentWeatherIconSmallUrl = QString("");
+ QUrl m_weatherCurrentWeatherIconSmallDarkBgUrl = QString("");
+ QUrl m_weatherCurrentWeatherIconMediumUrl = QString("");
+ QUrl m_weatherCurrentWeatherIconMediumDarkBgUrl = QString("");
+ QUrl m_weatherCurrentWeatherIconLargeUrl = QString("");
+ QUrl m_weatherCurrentWeatherIconLargeDarkBgUrl = QString("");
+
+ QString m_weatherLowTemperature = "";
+ QUrl m_weatherLowTemperatureArrowSmallUrl = QString("");
+ QUrl m_weatherLowTemperatureArrowSmallDarkBgUrl = QString("");
+ QUrl m_weatherLowTemperatureArrowMediumUrl = QString("");
+ QUrl m_weatherLowTemperatureArrowMediumDarkBgUrl = QString("");
+ QUrl m_weatherLowTemperatureArrowLargeUrl = QString("");
+ QUrl m_weatherLowTemperatureArrowLargeDarkBgUrl = QString("");
+
+ QString m_weatherHighTemperature = "";
+ QUrl m_weatherHighTemperatureArrowSmallUrl = QString("");
+ QUrl m_weatherHighTemperatureArrowSmallDarkBgUrl = QString("");
+ QUrl m_weatherHighTemperatureArrowMediumUrl = QString("");
+ QUrl m_weatherHighTemperatureArrowMediumDarkBgUrl = QString("");
+ QUrl m_weatherHighTemperatureArrowLargeUrl = QString("");
+ QUrl m_weatherHighTemperatureArrowLargeDarkBgUrl = QString("");
+};
+
+#endif // GUIMETADATA_H
diff --git a/voice-capabilities/guimetadatamessage.cpp b/voice-capabilities/guimetadatamessage.cpp
new file mode 100644
index 0000000..1613c12
--- /dev/null
+++ b/voice-capabilities/guimetadatamessage.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 Konsulko Group
+ *
+ * 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 <QDebug>
+#include <QJsonArray>
+#include <QJsonDocument>
+#include <QJsonObject>
+
+#include "guimetadatamessage.h"
+
+bool GuiMetadataCapabilityMessage::createRequest(QString verb, QJsonObject parameter)
+{
+ if (!verbs.contains(verb))
+ return false;
+
+ return Message::createRequest("vshl-capabilities", verb, parameter);
+}
diff --git a/voice-capabilities/guimetadatamessage.h b/voice-capabilities/guimetadatamessage.h
new file mode 100644
index 0000000..7f0854f
--- /dev/null
+++ b/voice-capabilities/guimetadatamessage.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2020 Konsulko Group
+ *
+ * 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 GUIMETADATA_MESSAGE_H
+#define GUIMETADATA_MESSAGE_H
+
+#include "message.h"
+
+class GuiMetadataCapabilityMessage : public Message
+{
+ Q_OBJECT
+public:
+ bool isGuiMetadataRenderTemplateEvent() const {
+ return (this->eventName() == "render_template"); };
+ bool isGuiMetadataClearTemplateEvent() const {
+ return (this->eventName() == "clear_template"); };
+ bool createRequest(QString verb, QJsonObject parameter);
+
+private:
+ QStringList verbs {
+ "guimetadata/subscribe",
+ };
+};
+
+#endif // GUIMETADATA_MESSAGE_H