diff --git a/debian/control b/debian/control index 20f9b769..71622413 100644 --- a/debian/control +++ b/debian/control @@ -231,6 +231,21 @@ Description: nymea.io plugin for dweet.io This package will install the nymea.io plugin for dweet.io +Package: nymea-plugin-dynatrace +Architecture: any +Depends: ${shlibs:Depends}, + ${misc:Depends}, + nymea-plugins-translations, +Description: nymea.io plugin for dynatrace + The nymea daemon is a plugin based IoT (Internet of Things) server. The + server works like a translator for devices, things and services and + allows them to interact. + With the powerful rule engine you are able to connect any device available + in the system and create individual scenes and behaviors for your environment. + . + This package will install the nymea.io plugin for dynatrace + + Package: nymea-plugin-elgato Architecture: any Depends: ${shlibs:Depends}, @@ -1037,6 +1052,7 @@ Depends: nymea-plugin-boblight, nymea-plugin-serialportcommander, nymea-plugin-systemmonitor, nymea-plugin-onewire, + nymea-plugin-dynatrace, Replaces: guh-plugins-maker Description: Plugins for nymea IoT server - Meta package for makers, tinkers and hackers The nymea daemon is a plugin based IoT (Internet of Things) server. The diff --git a/debian/nymea-plugin-dynatrace.install.in b/debian/nymea-plugin-dynatrace.install.in new file mode 100644 index 00000000..428b30a2 --- /dev/null +++ b/debian/nymea-plugin-dynatrace.install.in @@ -0,0 +1 @@ +usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationplugindynatrace.so diff --git a/dynatrace/README.md b/dynatrace/README.md new file mode 100644 index 00000000..8f78c5b8 --- /dev/null +++ b/dynatrace/README.md @@ -0,0 +1,26 @@ +# Dynatrace + +This plug-in enables nymea to control the Dynatrace Ufo. + +The Dynatrace UFO is a sophisticated status light by Dynatrace. More information about the the UFO can be found +(here)[https://www.dynatrace.com/news/blog/using-dynatrace-devops-pipeline-state-ufo/]. 3D print layouts and +build instructions for your own UFO are available at this (github page)[https://github.com/Dynatrace/ufo]. + +This nymea integration supports auto discovering UFOs in the network and set them up as a color light in nymea. +Each ring can as well as the top logo can be controlled individually and morph and rotate effects can be enabled. + +## Requirements + +* The UFO device must be in the same local are network as nymea. +* TCP sockets on port 80 must not be blocked by the router. +* The package "nymea-plugin-dynatrace" must be installed. + + +* Plug it in! +* Press the little black dot on the top. The UFO starts blinking blue and now offers a WiFi hotspot with the name “ufo” +* Connect to that hotspot, browse to http://192.168.4.1 +* Through the Web UI connect to your own WiFi. You can also do it via the REST API: http://192.168.4.1/api?ssid=&pwd= +* Remember: WPA2 works well where Enterprise WPA2 is currently not supported +* While it reboots itself it will blink yellow. Once it has its assigned IP Address it will start visualizing its IP Address through a special „blink code“ as explained in the Quick Start Guide! +* Remember: the UFO will also try to register its hostname as „ufo“ with your DHCP server. If that works you can simply browse to http://ufo + diff --git a/dynatrace/dynatrace.pro b/dynatrace/dynatrace.pro new file mode 100644 index 00000000..9ab1b668 --- /dev/null +++ b/dynatrace/dynatrace.pro @@ -0,0 +1,13 @@ +include(../plugins.pri) + +QT += network + +TARGET = $$qtLibraryTarget(nymea_integrationplugindynatrace) + +SOURCES += \ + integrationplugindynatrace.cpp \ + ufo.cpp + +HEADERS += \ + integrationplugindynatrace.h \ + ufo.h diff --git a/dynatrace/integrationplugindynatrace.cpp b/dynatrace/integrationplugindynatrace.cpp new file mode 100644 index 00000000..da646363 --- /dev/null +++ b/dynatrace/integrationplugindynatrace.cpp @@ -0,0 +1,373 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU Lesser General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; version 3. This project is distributed in the hope that +* it will be useful, but WITHOUT ANY WARRANTY; without even the implied +* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "integrationplugindynatrace.h" +#include "plugininfo.h" +#include "network/networkaccessmanager.h" + +#include +#include +#include +#include +#include + +IntegrationPluginDynatrace::IntegrationPluginDynatrace() +{ +} + +void IntegrationPluginDynatrace::discoverThings(ThingDiscoveryInfo *info) +{ + // NOTE: QHostInfo::lookupHost will call in from another thread using the Funtor syntax! + // https://bugreports.qt.io/browse/QTBUG-83073 + // Using the old school syntax... + int id = QHostInfo::lookupHost("ufo.home", this, SLOT(resolveIds(const QHostInfo &))); + m_asyncDiscoveries.insert(id, info); +} + +void IntegrationPluginDynatrace::resolveIds(const QHostInfo &host) +{ + int id = host.lookupId(); + + if (!m_asyncDiscoveries.contains(id)) { + qCWarning(dcDynatrace()) << "Discvery result came in but request has vanished..."; + return; + } + + ThingDiscoveryInfo *info = m_asyncDiscoveries.take(id); + if (host.error() != QHostInfo::NoError) { + qCDebug(dcDynatrace()) << "Lookup failed:" << host.errorString(); + info->finish(Thing::ThingErrorHardwareFailure, QT_TR_NOOP("An error happened discovering the UFO in the network.")); + return; + } + + QList *pendingInfoRequests = new QList(); + + foreach (QHostAddress address, host.addresses()) { + qCDebug(dcDynatrace()) << "Found IP address" << address.toString(); + + QNetworkRequest infoRequest("http://" + address.toString() + "/info"); + QNetworkReply *reply = hardwareManager()->networkManager()->get(infoRequest); + + pendingInfoRequests->append(reply); + + connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); + connect(reply, &QNetworkReply::finished, info, [this, info, reply, address, pendingInfoRequests](){ + pendingInfoRequests->removeAll(reply); + + QJsonParseError error; + QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error == QJsonParseError::NoError) { + QString id = data.toVariant().toMap().value("ufoid").toString(); + + ThingDescriptor descriptor(ufoThingClassId, "UFO", address.toString()); + ParamList params; + params << Param(ufoThingIdParamTypeId, id); + params << Param(ufoThingHostParamTypeId, address.toString()); + descriptor.setParams(params); + + Things existingUfos = myThings().filterByParam(ufoThingIdParamTypeId, id); + if (!existingUfos.isEmpty()) { + descriptor.setThingId(existingUfos.first()->id()); + } + + info->addThingDescriptor(descriptor); + } + + if (pendingInfoRequests->isEmpty()) { + delete pendingInfoRequests; + info->finish(Thing::ThingErrorNoError); + } + + }); + } + + // In case we abort, make sure to clean up stuff + connect(info, &ThingDiscoveryInfo::aborted, this, [pendingInfoRequests](){ + delete pendingInfoRequests; + }); +} + +void IntegrationPluginDynatrace::setupThing(ThingSetupInfo *info) +{ + if (info->thing()->thingClassId() == ufoThingClassId) { + QHostAddress address = QHostAddress(info->thing()->paramValue(ufoThingHostParamTypeId).toString()); + QString id = info->thing()->paramValue(ufoThingIdParamTypeId).toString(); + if(id.isEmpty()) { //Probably a manual Thing setup + QUrl url; + url.setScheme("http"); + url.setHost(address.toString()); + url.setPath("/info", QUrl::ParsingMode::TolerantMode); + QNetworkRequest request; + request.setUrl(url); + QNetworkReply *reply = hardwareManager()->networkManager()->get(request); + connect(reply, &QNetworkReply::finished, this, [info, reply] { + reply->deleteLater(); + + QJsonParseError error; + QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error != QJsonParseError::NoError) { + info->finish(Thing::ThingErrorSetupFailed, error.errorString()); + } + QString id = data.toVariant().toMap().value("ufoid").toString(); + info->thing()->setParamValue(ufoThingIdParamTypeId, id); + info->finish(Thing::ThingErrorNoError); + }); + } else { + // Discovery Thing setup or Things setup caused by nymea restart + info->finish(Thing::ThingErrorNoError); + } + } else { + qCWarning(dcDynatrace()) << "Setup thing: Unhandled ThingClassId" << info->thing()->thingClassId(); + info->finish(Thing::ThingErrorSetupFailed); + } +} + +void IntegrationPluginDynatrace::postSetupThing(Thing *thing) +{ + if (thing->thingClassId() == ufoThingClassId) { + thing->setStateValue(ufoConnectedStateTypeId, true); + thing->setStateValue(ufoPowerStateTypeId, false); + thing->setStateValue(ufoLogoStateTypeId, false); + thing->setStateValue(ufoEffectTopStateTypeId, "None"); + thing->setStateValue(ufoEffectBottomStateTypeId, "None"); + + QHostAddress address = QHostAddress(thing->paramValue(ufoThingHostParamTypeId).toString()); + Ufo *ufo = new Ufo(hardwareManager()->networkManager(), address, this); + connect(ufo, &Ufo::connectionChanged, this, &IntegrationPluginDynatrace::onConnectionChanged); + m_ufoConnections.insert(thing->id(), ufo); + // Set all off + ufo->setLogo(QColor(Qt::black), QColor(Qt::black), QColor(Qt::black), QColor(Qt::black)); + ufo->setBackgroundColor(true, true, true, true, QColor(Qt::black)); + } + + if(!m_pluginTimer) { + m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(60); + connect(m_pluginTimer, &PluginTimer::timeout, this, [this]() { + foreach (Ufo *ufo, m_ufoConnections.values()) { + ufo->getId(); + } + }); + } +} + +void IntegrationPluginDynatrace::executeAction(ThingActionInfo *info) +{ + Thing *thing = info->thing(); + Action action = info->action(); + + if (thing->thingClassId() == ufoThingClassId) { + Ufo *ufo = m_ufoConnections.value(thing->id()); + if (!ufo) + return; + if (action.actionTypeId() == ufoLogoActionTypeId) { + bool power = action.param(ufoLogoActionLogoParamTypeId).value().toBool(); + thing->setStateValue(ufoLogoStateTypeId, power); + if (power) { + int brightness = thing->stateValue(ufoBrightnessActionBrightnessParamTypeId).toInt(); + QColor color = QColor(thing->stateValue(ufoLogoColorStateTypeId).toString()); + color.setHsv(color.hue(), color.saturation(), brightness*2.55); + ufo->setLogo(color, color, color, color); + } else { + ufo->setLogo(QColor(Qt::black), QColor(Qt::black), QColor(Qt::black), QColor(Qt::black)); + } + info->finish(Thing::ThingErrorNoError); + + } else if (action.actionTypeId() == ufoPowerActionTypeId) { + bool power = action.param(ufoPowerActionPowerParamTypeId).value().toBool(); + thing->setStateValue(ufoPowerStateTypeId, power); + if (power) { + int brightness = thing->stateValue(ufoBrightnessActionBrightnessParamTypeId).toInt(); + QColor color = QColor(thing->stateValue(ufoColorStateTypeId).toString()); + color.setHsv(color.hue(), color.saturation(), brightness*2.55); + thing->setStateValue(ufoLogoStateTypeId, true); + ufo->setLogo(color, color, color, color); + ufo->setBackgroundColor(true, true, true, true, color); + thing->setStateValue(ufoEffectTopStateTypeId, "None"); + thing->setStateValue(ufoEffectBottomStateTypeId, "None"); + thing->setStateValue(ufoLogoColorStateTypeId, color); + thing->setStateValue(ufoTopColorStateTypeId, color); + thing->setStateValue(ufoBottomColorStateTypeId, color); + } else { + ufo->setLogo(QColor(Qt::black), QColor(Qt::black), QColor(Qt::black), QColor(Qt::black)); + thing->setStateValue(ufoLogoStateTypeId, false); + ufo->setBackgroundColor(true, true, true, true, QColor(Qt::black)); + thing->setStateValue(ufoEffectTopStateTypeId, "None"); + thing->setStateValue(ufoEffectBottomStateTypeId, "None"); + } + info->finish(Thing::ThingErrorNoError); + + } else if (action.actionTypeId() == ufoBrightnessActionTypeId) { + int brightness = action.param(ufoBrightnessActionBrightnessParamTypeId).value().toInt(); + thing->setStateValue(ufoBrightnessStateTypeId, brightness); + QColor color = QColor(thing->stateValue(ufoColorStateTypeId).toString()); + color.setHsv(color.hue(), color.saturation(), brightness*2.55); + if (thing->stateValue(ufoLogoStateTypeId).toBool()) { + ufo->setLogo(color, color, color, color); + } + ufo->setBackgroundColor(true, false, true, false, color); + info->finish(Thing::ThingErrorNoError); + } else if (action.actionTypeId() == ufoColorActionTypeId) { + QColor color = QColor(action.param(ufoColorActionColorParamTypeId).value().toString()); + int brightness = thing->stateValue(ufoBrightnessStateTypeId).toInt(); + thing->setStateValue(ufoColorStateTypeId, color); + thing->setStateValue(ufoLogoColorStateTypeId, color); + thing->setStateValue(ufoTopColorStateTypeId, color); + thing->setStateValue(ufoBottomColorStateTypeId, color); + color.setHsv(color.hue(), color.saturation(), brightness*2.55); + if (thing->stateValue(ufoLogoStateTypeId).toBool()) { + ufo->setLogo(color, color, color, color); + } + ufo->setBackgroundColor(true, false, true, false, color); + info->finish(Thing::ThingErrorNoError); + } else if (action.actionTypeId() == ufoColorTemperatureActionTypeId) { + int mired= thing->stateValue(ufoColorTemperatureActionColorTemperatureParamTypeId).toInt(); + thing->setStateValue(ufoColorTemperatureStateTypeId, mired); + int brightness = thing->stateValue(ufoBrightnessActionBrightnessParamTypeId).toInt(); + QColor color(Qt::white); + color.setBlue(static_cast((mired-153)*0.73)); + color.setHsv(color.hue(), color.saturation(), brightness*2.55); + if (thing->stateValue(ufoLogoStateTypeId).toBool()) { + ufo->setLogo(color, color, color, color); + } + thing->setStateValue(ufoColorStateTypeId, color); + thing->setStateValue(ufoLogoColorStateTypeId, color); + thing->setStateValue(ufoTopColorStateTypeId, color); + thing->setStateValue(ufoBottomColorStateTypeId, color); + ufo->setBackgroundColor(true, false, true, false, color); + info->finish(Thing::ThingErrorNoError); + + } else if (action.actionTypeId() == ufoEffectTopActionTypeId) { + QString effect = action.param(ufoEffectTopActionEffectTopParamTypeId).value().toString(); + int brightness = thing->stateValue(ufoBrightnessActionBrightnessParamTypeId).toInt(); + QColor color = QColor(thing->stateValue(ufoColorStateTypeId).toString()); + color.setHsv(color.hue(), color.saturation(), brightness*2.55); + if (effect == "None") { + ufo->setBackgroundColor(true, true, false, false, color); + } else if (effect == "Whirl") { + ufo->startWhirl(true, false, color, 500, true); + } else if (effect == "Morph") { + ufo->startMorph(true, false, color, 250, 8); + } + info->finish(Thing::ThingErrorNoError); + } else if (action.actionTypeId() == ufoEffectBottomActionTypeId) { + QString effect = action.param(ufoEffectBottomActionEffectBottomParamTypeId).value().toString(); + int brightness = thing->stateValue(ufoBrightnessActionBrightnessParamTypeId).toInt(); + QColor color = QColor(thing->stateValue(ufoColorStateTypeId).toString()); + color.setHsv(color.hue(), color.saturation(), brightness*2.55); + if (effect == "None") { + ufo->setBackgroundColor(false, false, true, true, color); + } else if (effect == "Whirl") { + ufo->startWhirl(false, true, color, 500, true); + } else if (effect == "Morph") { + ufo->startMorph(false, true, color, 250, 8); + } + info->finish(Thing::ThingErrorNoError); + } else if (action.actionTypeId() == ufoLogoColorActionTypeId) { + QColor color = QColor(action.param(ufoLogoColorActionLogoColorParamTypeId).value().toString()); + int brightness = thing->stateValue(ufoBrightnessStateTypeId).toInt(); + thing->setStateValue(ufoLogoColorStateTypeId, color); + thing->setStateValue(ufoLogoStateTypeId, true); + color.setHsv(color.hue(), color.saturation(), brightness*2.55); + ufo->setLogo(color, color, color, color); + info->finish(Thing::ThingErrorNoError); + } else if (action.actionTypeId() == ufoTopColorActionTypeId) { + QColor color = QColor(action.param(ufoTopColorActionTopColorParamTypeId).value().toString()); + int brightness = thing->stateValue(ufoBrightnessStateTypeId).toInt(); + thing->setStateValue(ufoTopColorStateTypeId, color); + thing->setStateValue(ufoPowerStateTypeId, true); + color.setHsv(color.hue(), color.saturation(), brightness*2.55); + ufo->setBackgroundColor(true, false, false, false, color); + info->finish(Thing::ThingErrorNoError); + } else if (action.actionTypeId() == ufoBottomColorActionTypeId) { + QColor color = QColor(action.param(ufoBottomColorActionBottomColorParamTypeId).value().toString()); + int brightness = thing->stateValue(ufoBrightnessStateTypeId).toInt(); + thing->setStateValue(ufoBottomColorStateTypeId, color); + thing->setStateValue(ufoPowerStateTypeId, true); + color.setHsv(color.hue(), color.saturation(), brightness*2.55); + ufo->setBackgroundColor(false, false, true, false, color); + info->finish(Thing::ThingErrorNoError); + } else { + qCWarning(dcDynatrace()) << "Execute action: Unhandled actionTypeId"; + info->finish(Thing::ThingErrorHardwareFailure); + } + } else { + qCWarning(dcDynatrace()) << "Execute action: Unhandled ThingClass"; + info->finish(Thing::ThingErrorHardwareFailure); + } +} + +void IntegrationPluginDynatrace::thingRemoved(Thing *thing) +{ + if (thing->thingClassId() == ufoThingClassId) { + if (m_ufoConnections.contains(thing->id())){ + Ufo *ufo = m_ufoConnections.take(thing->id()); + ufo->deleteLater(); + } + } + + if (myThings().isEmpty() && m_pluginTimer) { + m_pluginTimer->deleteLater(); + m_pluginTimer = nullptr; + } +} + +void IntegrationPluginDynatrace::getId(const QHostAddress &address) +{ + QUrl url; + url.setScheme("http"); + url.setHost(address.toString()); + url.setPath("/info", QUrl::ParsingMode::TolerantMode); + QNetworkRequest request; + request.setUrl(url); + QNetworkReply *reply = hardwareManager()->networkManager()->get(request); + connect(reply, &QNetworkReply::finished, this, [reply, this] { + reply->deleteLater(); + + QJsonParseError error; + QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error != QJsonParseError::NoError) + return; + + QString id = data.toVariant().toMap().value("ufoid").toString(); + if (m_asyncSetup.contains(reply->url().host())) { + ThingSetupInfo *info = m_asyncSetup.value(reply->url().host()); + info->finish(Thing::ThingErrorNoError); + } + }); +} + +void IntegrationPluginDynatrace::onConnectionChanged(bool connected) +{ + Ufo *ufo = static_cast(sender()); + Thing *thing = myThings().findById(m_ufoConnections.key(ufo)); + if (!thing) + return; + thing->setStateValue(ufoConnectedStateTypeId, connected); +} diff --git a/dynatrace/integrationplugindynatrace.h b/dynatrace/integrationplugindynatrace.h new file mode 100644 index 00000000..cc7494be --- /dev/null +++ b/dynatrace/integrationplugindynatrace.h @@ -0,0 +1,73 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU Lesser General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; version 3. This project is distributed in the hope that +* it will be useful, but WITHOUT ANY WARRANTY; without even the implied +* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef INTEGRATIONPLUGINDYNATRACE_H +#define INTEGRATIONPLUGINDYNATRACE_H + +#include "plugintimer.h" +#include "integrations/integrationplugin.h" +#include "network/oauth2.h" +#include "ufo.h" + +#include +#include +#include + +class IntegrationPluginDynatrace : public IntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationplugindynatrace.json") + Q_INTERFACES(IntegrationPlugin) + +public: + explicit IntegrationPluginDynatrace(); + void discoverThings(ThingDiscoveryInfo *info) override; + void setupThing(ThingSetupInfo *info) override; + void postSetupThing(Thing *thing) override; + void executeAction(ThingActionInfo *info) override; + void thingRemoved(Thing *thing) override; + + +private slots: + void onConnectionChanged(bool connected); + + void resolveIds(const QHostInfo &host); + +private: + PluginTimer *m_pluginTimer = nullptr; + QHash m_ufoConnections; + QHash m_asyncActions; + QHash m_asyncSetup; + QHash m_asyncDiscoveries; + + void getId(const QHostAddress &address); +}; + +#endif // INTEGRATIONPLUGINDYNATRACE_H diff --git a/dynatrace/integrationplugindynatrace.json b/dynatrace/integrationplugindynatrace.json new file mode 100644 index 00000000..54241891 --- /dev/null +++ b/dynatrace/integrationplugindynatrace.json @@ -0,0 +1,165 @@ +{ + "displayName": "Dynatrace", + "name": "dynatrace", + "id": "a8451bd7-69cb-4106-968f-1206a5736368", + "vendors": [ + { + "name": "Dynatrace", + "displayName": "Dynatrace", + "id": "31b402be-1562-4335-aa83-d1c1166db570", + "thingClasses": [ + { + "id": "6271f010-0b0a-4f29-b894-0611bb5f3dcc", + "name": "ufo", + "displayName": "UFO", + "createMethods": ["user", "discovery"], + "interfaces": ["colorlight", "connectable"], + "paramTypes": [ + { + "id": "3e14968b-954e-4e85-ae79-3de9ae4fe951", + "name": "host", + "displayName": "Host address", + "type" : "QString", + "inputType": "IPv4Address", + "readOnly": true + }, + { + "id": "142c25c0-03e3-478e-b5c3-3d072f668cc4", + "name": "id", + "displayName": "Id", + "type" : "QString", + "readOnly": true + } + ], + "stateTypes": [ + { + "id": "1a439907-e810-4dea-b357-dd32281896e7", + "name": "connected", + "displayName": "Reachable", + "displayNameEvent": "Reachable changed", + "defaultValue": false, + "cached": false, + "type": "bool" + }, + { + "id": "a9c123e2-db78-40d3-a422-7e4817d50984", + "name": "logo", + "displayName": "Logo", + "displayNameEvent": "Logo changed", + "displayNameAction": "Set logo", + "defaultValue": false, + "type": "bool", + "writable": true + }, + { + "id": "14ac8d16-72be-4530-a2ce-dd5589ce8dd7", + "name": "power", + "displayName": "Power", + "displayNameEvent": "Power changed", + "displayNameAction": "Set power", + "type": "bool", + "defaultValue": false, + "writable": true + }, + { + "id": "60fa917b-8702-4ff2-90b8-9c8c616bb21f", + "name": "colorTemperature", + "displayName": "Color temperature", + "displayNameEvent": "Color temperature changed", + "displayNameAction": "Set color temperature", + "type": "int", + "unit": "Mired", + "defaultValue": 170, + "minValue": 153, + "maxValue": 500, + "writable": true + }, + { + "id": "9535fd99-05c6-449f-80a2-8daf61d9b9b0", + "name": "color", + "displayName": "Color", + "displayNameEvent": "Color changed", + "displayNameAction": "Set color", + "type": "QColor", + "defaultValue": "#000000", + "writable": true + }, + { + "id": "1adb2df8-7ba1-48b8-b0da-d67085efe041", + "name": "brightness", + "displayName": "Brightness", + "displayNameEvent": "Brightness changed", + "displayNameAction": "Set brigtness", + "type": "int", + "unit": "Percentage", + "defaultValue": 0, + "minValue": 0, + "maxValue": 100, + "writable": true + }, + { + "id": "53da0021-974a-434a-94ac-3f187aad1480", + "name": "effectTop", + "displayName": "Effect top", + "displayNameEvent": "Effect top changed", + "displayNameAction": "Set top effect", + "type": "QString", + "defaultValue": "None", + "possibleValues": [ + "None", + "Morph", + "Whirl" + ], + "writable": true + }, + { + "id": "0fab896b-9900-4375-96c0-0d38460cee65", + "name": "effectBottom", + "displayName": "Effect bottom", + "displayNameEvent": "Effect bottom changed", + "displayNameAction": "Set bottom effect", + "type": "QString", + "defaultValue": "None", + "possibleValues": [ + "None", + "Morph", + "Whirl" + ], + "writable": true + }, + { + "id": "d3eb4a99-20cc-4d47-af7d-33453aca2087", + "name": "logoColor", + "displayName": "Logo color", + "displayNameEvent": "Logo color changed", + "displayNameAction": "Set logo color", + "type": "QColor", + "defaultValue": "#000000", + "writable": true + }, + { + "id": "b378290a-468f-45ef-9d65-00546737ce9b", + "name": "topColor", + "displayName": "Top color", + "displayNameEvent": "Top color changed", + "displayNameAction": "Set top color", + "type": "QColor", + "defaultValue": "#000000", + "writable": true + }, + { + "id": "ef2a8d5b-82d4-43d5-b9ec-82ef5662b971", + "name": "bottomColor", + "displayName": "Bottom color", + "displayNameEvent": "Bottom color changed", + "displayNameAction": "Set bottom color", + "type": "QColor", + "defaultValue": "#000000", + "writable": true + } + ] + } + ] + } + ] +} diff --git a/dynatrace/translations/a8451bd7-69cb-4106-968f-1206a5736368-de.ts b/dynatrace/translations/a8451bd7-69cb-4106-968f-1206a5736368-de.ts new file mode 100644 index 00000000..9119892e --- /dev/null +++ b/dynatrace/translations/a8451bd7-69cb-4106-968f-1206a5736368-de.ts @@ -0,0 +1,297 @@ + + + + + IntegrationPluginDynatrace + + + An error happened discovering the UFO in the network. + Ein Netzwerkfehler ist beim Auffinden des UFOs aufgetreten. + + + + dynatrace + + + + + Brightness + The name of the ParamType (ThingClass: ufo, ActionType: brightness, ID: {1adb2df8-7ba1-48b8-b0da-d67085efe041}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: brightness, ID: {1adb2df8-7ba1-48b8-b0da-d67085efe041}) +---------- +The name of the StateType ({1adb2df8-7ba1-48b8-b0da-d67085efe041}) of ThingClass ufo + Helligkeit + + + + Brightness changed + The name of the EventType ({1adb2df8-7ba1-48b8-b0da-d67085efe041}) of ThingClass ufo + Helligkeit geändert + + + + + + Color + The name of the ParamType (ThingClass: ufo, ActionType: color, ID: {9535fd99-05c6-449f-80a2-8daf61d9b9b0}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: color, ID: {9535fd99-05c6-449f-80a2-8daf61d9b9b0}) +---------- +The name of the StateType ({9535fd99-05c6-449f-80a2-8daf61d9b9b0}) of ThingClass ufo + Farbe + + + + Color changed + The name of the EventType ({9535fd99-05c6-449f-80a2-8daf61d9b9b0}) of ThingClass ufo + Farbe geändert + + + + + + Color temperature + The name of the ParamType (ThingClass: ufo, ActionType: colorTemperature, ID: {60fa917b-8702-4ff2-90b8-9c8c616bb21f}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: colorTemperature, ID: {60fa917b-8702-4ff2-90b8-9c8c616bb21f}) +---------- +The name of the StateType ({60fa917b-8702-4ff2-90b8-9c8c616bb21f}) of ThingClass ufo + Farbtemperatur + + + + Color temperature changed + The name of the EventType ({60fa917b-8702-4ff2-90b8-9c8c616bb21f}) of ThingClass ufo + Farbtemperatur geändert + + + + + Dynatrace + The name of the vendor ({31b402be-1562-4335-aa83-d1c1166db570}) +---------- +The name of the plugin dynatrace ({a8451bd7-69cb-4106-968f-1206a5736368}) + Dynatrace + + + + + + Bottom color + The name of the ParamType (ThingClass: ufo, ActionType: bottomColor, ID: {ef2a8d5b-82d4-43d5-b9ec-82ef5662b971}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: bottomColor, ID: {ef2a8d5b-82d4-43d5-b9ec-82ef5662b971}) +---------- +The name of the StateType ({ef2a8d5b-82d4-43d5-b9ec-82ef5662b971}) of ThingClass ufo + Farbe unten + + + + Bottom color changed + The name of the EventType ({ef2a8d5b-82d4-43d5-b9ec-82ef5662b971}) of ThingClass ufo + Farbe unten geändert + + + + + + Effect bottom + The name of the ParamType (ThingClass: ufo, ActionType: effectBottom, ID: {0fab896b-9900-4375-96c0-0d38460cee65}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: effectBottom, ID: {0fab896b-9900-4375-96c0-0d38460cee65}) +---------- +The name of the StateType ({0fab896b-9900-4375-96c0-0d38460cee65}) of ThingClass ufo + Effekt unten + + + + Effect bottom changed + The name of the EventType ({0fab896b-9900-4375-96c0-0d38460cee65}) of ThingClass ufo + Effekt unten geändert + + + + + + Effect top + The name of the ParamType (ThingClass: ufo, ActionType: effectTop, ID: {53da0021-974a-434a-94ac-3f187aad1480}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: effectTop, ID: {53da0021-974a-434a-94ac-3f187aad1480}) +---------- +The name of the StateType ({53da0021-974a-434a-94ac-3f187aad1480}) of ThingClass ufo + Effekt oben + + + + Effect top changed + The name of the EventType ({53da0021-974a-434a-94ac-3f187aad1480}) of ThingClass ufo + Effekt oben geändert + + + + Host address + The name of the ParamType (ThingClass: ufo, Type: thing, ID: {3e14968b-954e-4e85-ae79-3de9ae4fe951}) + IP Adresse + + + + Id + The name of the ParamType (ThingClass: ufo, Type: thing, ID: {142c25c0-03e3-478e-b5c3-3d072f668cc4}) + ID + + + + + + Logo + The name of the ParamType (ThingClass: ufo, ActionType: logo, ID: {a9c123e2-db78-40d3-a422-7e4817d50984}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: logo, ID: {a9c123e2-db78-40d3-a422-7e4817d50984}) +---------- +The name of the StateType ({a9c123e2-db78-40d3-a422-7e4817d50984}) of ThingClass ufo + Logo + + + + Logo changed + The name of the EventType ({a9c123e2-db78-40d3-a422-7e4817d50984}) of ThingClass ufo + Logo geändert + + + + + + Logo color + The name of the ParamType (ThingClass: ufo, ActionType: logoColor, ID: {d3eb4a99-20cc-4d47-af7d-33453aca2087}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: logoColor, ID: {d3eb4a99-20cc-4d47-af7d-33453aca2087}) +---------- +The name of the StateType ({d3eb4a99-20cc-4d47-af7d-33453aca2087}) of ThingClass ufo + Logo-Farbe + + + + Logo color changed + The name of the EventType ({d3eb4a99-20cc-4d47-af7d-33453aca2087}) of ThingClass ufo + Logo-Farbe geändert + + + + + + Power + The name of the ParamType (ThingClass: ufo, ActionType: power, ID: {14ac8d16-72be-4530-a2ce-dd5589ce8dd7}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: power, ID: {14ac8d16-72be-4530-a2ce-dd5589ce8dd7}) +---------- +The name of the StateType ({14ac8d16-72be-4530-a2ce-dd5589ce8dd7}) of ThingClass ufo + Eingeschaltet + + + + Power changed + The name of the EventType ({14ac8d16-72be-4530-a2ce-dd5589ce8dd7}) of ThingClass ufo + Ein- oder ausgeschaltet + + + + + Reachable + The name of the ParamType (ThingClass: ufo, EventType: connected, ID: {1a439907-e810-4dea-b357-dd32281896e7}) +---------- +The name of the StateType ({1a439907-e810-4dea-b357-dd32281896e7}) of ThingClass ufo + Erreichbar + + + + Reachable changed + The name of the EventType ({1a439907-e810-4dea-b357-dd32281896e7}) of ThingClass ufo + Erreichbarkeit geändert + + + + Set bottom color + The name of the ActionType ({ef2a8d5b-82d4-43d5-b9ec-82ef5662b971}) of ThingClass ufo + Setze Farbe unten + + + + Set bottom effect + The name of the ActionType ({0fab896b-9900-4375-96c0-0d38460cee65}) of ThingClass ufo + Setze Farbe oben + + + + Set brigtness + The name of the ActionType ({1adb2df8-7ba1-48b8-b0da-d67085efe041}) of ThingClass ufo + Setze Helligkeit + + + + Set color + The name of the ActionType ({9535fd99-05c6-449f-80a2-8daf61d9b9b0}) of ThingClass ufo + Setze Farbe + + + + Set color temperature + The name of the ActionType ({60fa917b-8702-4ff2-90b8-9c8c616bb21f}) of ThingClass ufo + Setze Farbtemperatur + + + + Set top color + The name of the ActionType ({b378290a-468f-45ef-9d65-00546737ce9b}) of ThingClass ufo + Setze Farbe oben + + + + Set top effect + The name of the ActionType ({53da0021-974a-434a-94ac-3f187aad1480}) of ThingClass ufo + Setze Effekt oben + + + + + + Top color + The name of the ParamType (ThingClass: ufo, ActionType: topColor, ID: {b378290a-468f-45ef-9d65-00546737ce9b}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: topColor, ID: {b378290a-468f-45ef-9d65-00546737ce9b}) +---------- +The name of the StateType ({b378290a-468f-45ef-9d65-00546737ce9b}) of ThingClass ufo + Farbe oben + + + + Top color changed + The name of the EventType ({b378290a-468f-45ef-9d65-00546737ce9b}) of ThingClass ufo + Farbe oben geändert + + + + UFO + The name of the ThingClass ({6271f010-0b0a-4f29-b894-0611bb5f3dcc}) + UFO + + + + Set logo + The name of the ActionType ({a9c123e2-db78-40d3-a422-7e4817d50984}) of ThingClass ufo + Setze Logo + + + + Set logo color + The name of the ActionType ({d3eb4a99-20cc-4d47-af7d-33453aca2087}) of ThingClass ufo + Setze Logo-Farbe + + + + Set power + The name of the ActionType ({14ac8d16-72be-4530-a2ce-dd5589ce8dd7}) of ThingClass ufo + Ein- oder ausschalten + + + diff --git a/dynatrace/translations/a8451bd7-69cb-4106-968f-1206a5736368-en_US.ts b/dynatrace/translations/a8451bd7-69cb-4106-968f-1206a5736368-en_US.ts new file mode 100644 index 00000000..a9ffb8f8 --- /dev/null +++ b/dynatrace/translations/a8451bd7-69cb-4106-968f-1206a5736368-en_US.ts @@ -0,0 +1,297 @@ + + + + + IntegrationPluginDynatrace + + + An error happened discovering the UFO in the network. + + + + + dynatrace + + + + + Brightness + The name of the ParamType (ThingClass: ufo, ActionType: brightness, ID: {1adb2df8-7ba1-48b8-b0da-d67085efe041}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: brightness, ID: {1adb2df8-7ba1-48b8-b0da-d67085efe041}) +---------- +The name of the StateType ({1adb2df8-7ba1-48b8-b0da-d67085efe041}) of ThingClass ufo + + + + + Brightness changed + The name of the EventType ({1adb2df8-7ba1-48b8-b0da-d67085efe041}) of ThingClass ufo + + + + + + + Color + The name of the ParamType (ThingClass: ufo, ActionType: color, ID: {9535fd99-05c6-449f-80a2-8daf61d9b9b0}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: color, ID: {9535fd99-05c6-449f-80a2-8daf61d9b9b0}) +---------- +The name of the StateType ({9535fd99-05c6-449f-80a2-8daf61d9b9b0}) of ThingClass ufo + + + + + Color changed + The name of the EventType ({9535fd99-05c6-449f-80a2-8daf61d9b9b0}) of ThingClass ufo + + + + + + + Color temperature + The name of the ParamType (ThingClass: ufo, ActionType: colorTemperature, ID: {60fa917b-8702-4ff2-90b8-9c8c616bb21f}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: colorTemperature, ID: {60fa917b-8702-4ff2-90b8-9c8c616bb21f}) +---------- +The name of the StateType ({60fa917b-8702-4ff2-90b8-9c8c616bb21f}) of ThingClass ufo + + + + + Color temperature changed + The name of the EventType ({60fa917b-8702-4ff2-90b8-9c8c616bb21f}) of ThingClass ufo + + + + + + Dynatrace + The name of the vendor ({31b402be-1562-4335-aa83-d1c1166db570}) +---------- +The name of the plugin dynatrace ({a8451bd7-69cb-4106-968f-1206a5736368}) + + + + + + + Bottom color + The name of the ParamType (ThingClass: ufo, ActionType: bottomColor, ID: {ef2a8d5b-82d4-43d5-b9ec-82ef5662b971}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: bottomColor, ID: {ef2a8d5b-82d4-43d5-b9ec-82ef5662b971}) +---------- +The name of the StateType ({ef2a8d5b-82d4-43d5-b9ec-82ef5662b971}) of ThingClass ufo + + + + + Bottom color changed + The name of the EventType ({ef2a8d5b-82d4-43d5-b9ec-82ef5662b971}) of ThingClass ufo + + + + + + + Effect bottom + The name of the ParamType (ThingClass: ufo, ActionType: effectBottom, ID: {0fab896b-9900-4375-96c0-0d38460cee65}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: effectBottom, ID: {0fab896b-9900-4375-96c0-0d38460cee65}) +---------- +The name of the StateType ({0fab896b-9900-4375-96c0-0d38460cee65}) of ThingClass ufo + + + + + Effect bottom changed + The name of the EventType ({0fab896b-9900-4375-96c0-0d38460cee65}) of ThingClass ufo + + + + + + + Effect top + The name of the ParamType (ThingClass: ufo, ActionType: effectTop, ID: {53da0021-974a-434a-94ac-3f187aad1480}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: effectTop, ID: {53da0021-974a-434a-94ac-3f187aad1480}) +---------- +The name of the StateType ({53da0021-974a-434a-94ac-3f187aad1480}) of ThingClass ufo + + + + + Effect top changed + The name of the EventType ({53da0021-974a-434a-94ac-3f187aad1480}) of ThingClass ufo + + + + + Host address + The name of the ParamType (ThingClass: ufo, Type: thing, ID: {3e14968b-954e-4e85-ae79-3de9ae4fe951}) + + + + + Id + The name of the ParamType (ThingClass: ufo, Type: thing, ID: {142c25c0-03e3-478e-b5c3-3d072f668cc4}) + + + + + + + Logo + The name of the ParamType (ThingClass: ufo, ActionType: logo, ID: {a9c123e2-db78-40d3-a422-7e4817d50984}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: logo, ID: {a9c123e2-db78-40d3-a422-7e4817d50984}) +---------- +The name of the StateType ({a9c123e2-db78-40d3-a422-7e4817d50984}) of ThingClass ufo + + + + + Logo changed + The name of the EventType ({a9c123e2-db78-40d3-a422-7e4817d50984}) of ThingClass ufo + + + + + + + Logo color + The name of the ParamType (ThingClass: ufo, ActionType: logoColor, ID: {d3eb4a99-20cc-4d47-af7d-33453aca2087}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: logoColor, ID: {d3eb4a99-20cc-4d47-af7d-33453aca2087}) +---------- +The name of the StateType ({d3eb4a99-20cc-4d47-af7d-33453aca2087}) of ThingClass ufo + + + + + Logo color changed + The name of the EventType ({d3eb4a99-20cc-4d47-af7d-33453aca2087}) of ThingClass ufo + + + + + + + Power + The name of the ParamType (ThingClass: ufo, ActionType: power, ID: {14ac8d16-72be-4530-a2ce-dd5589ce8dd7}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: power, ID: {14ac8d16-72be-4530-a2ce-dd5589ce8dd7}) +---------- +The name of the StateType ({14ac8d16-72be-4530-a2ce-dd5589ce8dd7}) of ThingClass ufo + + + + + Power changed + The name of the EventType ({14ac8d16-72be-4530-a2ce-dd5589ce8dd7}) of ThingClass ufo + + + + + + Reachable + The name of the ParamType (ThingClass: ufo, EventType: connected, ID: {1a439907-e810-4dea-b357-dd32281896e7}) +---------- +The name of the StateType ({1a439907-e810-4dea-b357-dd32281896e7}) of ThingClass ufo + + + + + Reachable changed + The name of the EventType ({1a439907-e810-4dea-b357-dd32281896e7}) of ThingClass ufo + + + + + Set bottom color + The name of the ActionType ({ef2a8d5b-82d4-43d5-b9ec-82ef5662b971}) of ThingClass ufo + + + + + Set bottom effect + The name of the ActionType ({0fab896b-9900-4375-96c0-0d38460cee65}) of ThingClass ufo + + + + + Set brigtness + The name of the ActionType ({1adb2df8-7ba1-48b8-b0da-d67085efe041}) of ThingClass ufo + + + + + Set color + The name of the ActionType ({9535fd99-05c6-449f-80a2-8daf61d9b9b0}) of ThingClass ufo + + + + + Set color temperature + The name of the ActionType ({60fa917b-8702-4ff2-90b8-9c8c616bb21f}) of ThingClass ufo + + + + + Set top color + The name of the ActionType ({b378290a-468f-45ef-9d65-00546737ce9b}) of ThingClass ufo + + + + + Set top effect + The name of the ActionType ({53da0021-974a-434a-94ac-3f187aad1480}) of ThingClass ufo + + + + + + + Top color + The name of the ParamType (ThingClass: ufo, ActionType: topColor, ID: {b378290a-468f-45ef-9d65-00546737ce9b}) +---------- +The name of the ParamType (ThingClass: ufo, EventType: topColor, ID: {b378290a-468f-45ef-9d65-00546737ce9b}) +---------- +The name of the StateType ({b378290a-468f-45ef-9d65-00546737ce9b}) of ThingClass ufo + + + + + Top color changed + The name of the EventType ({b378290a-468f-45ef-9d65-00546737ce9b}) of ThingClass ufo + + + + + UFO + The name of the ThingClass ({6271f010-0b0a-4f29-b894-0611bb5f3dcc}) + + + + + Set logo + The name of the ActionType ({a9c123e2-db78-40d3-a422-7e4817d50984}) of ThingClass ufo + + + + + Set logo color + The name of the ActionType ({d3eb4a99-20cc-4d47-af7d-33453aca2087}) of ThingClass ufo + + + + + Set power + The name of the ActionType ({14ac8d16-72be-4530-a2ce-dd5589ce8dd7}) of ThingClass ufo + + + + diff --git a/dynatrace/ufo.cpp b/dynatrace/ufo.cpp new file mode 100644 index 00000000..28727bca --- /dev/null +++ b/dynatrace/ufo.cpp @@ -0,0 +1,277 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU Lesser General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; version 3. This project is distributed in the hope that +* it will be useful, but WITHOUT ANY WARRANTY; without even the implied +* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "ufo.h" +#include "extern-plugininfo.h" + +#include +#include + +Ufo::Ufo(NetworkAccessManager *networkManager, const QHostAddress &address, QObject *parent) : + QObject(parent), + m_networkManager(networkManager), + m_address(address) +{ + +} + +void Ufo::getId() +{ + QUrl url; + url.setScheme("http"); + url.setHost(m_address.toString()); + url.setPath("/info", QUrl::ParsingMode::TolerantMode); + QNetworkRequest request; + request.setUrl(url); + QNetworkReply *reply = m_networkManager->get(request); + connect(reply, &QNetworkReply::finished, this, [reply, this] { + reply->deleteLater(); + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + // Check HTTP status code + if (status != 200 || reply->error() != QNetworkReply::NoError) { + qCWarning(dcDynatrace()) << "Request error:" << status << reply->errorString(); + emit connectionChanged(false); + return; + } + emit connectionChanged(true); + QJsonParseError error; + QJsonDocument data = QJsonDocument::fromJson(reply->readAll(), &error); + if (error.error != QJsonParseError::NoError){ + qCWarning(dcDynatrace()) << "JSON parsing error:" << error.errorString(); + return; + } + + QString id = data.toVariant().toMap().value("ufoid").toString(); + emit idReceived(id); + }); +} + +void Ufo::resetLogo() +{ + QUrl url; + url.setScheme("http"); + url.setHost(m_address.toString()); + url.setPath("/api"); + url.setQuery("logo_reset"); + QNetworkRequest request; + request.setUrl(url); + qCDebug(dcDynatrace()) << "Sending request" << url; + QNetworkReply *reply = m_networkManager->get(request); + connect(reply, &QNetworkReply::finished, this, [reply, this] { + reply->deleteLater(); + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + // Check HTTP status code + if (status != 200 || reply->error() != QNetworkReply::NoError) { + qCWarning(dcDynatrace()) << "Request error:" << status << reply->errorString(); + emit connectionChanged(false); + return; + } + emit connectionChanged(true); + }); +} + +void Ufo::setLogo(QColor led1, QColor led2, QColor led3, QColor led4) +{ + QUrl url; + url.setScheme("http"); + url.setHost(m_address.toString()); + url.setPath("/api"); + QUrlQuery query; + query.addQueryItem("logo", led1.name().remove(0,1)+"|"+led2.name().remove(0,1)+"|"+led3.name().remove(0,1)+"|"+led4.name().remove(0,1)); + url.setQuery(query); + QNetworkRequest request; + request.setUrl(url); + + qCDebug(dcDynatrace()) << "Sending request" << url; + QNetworkReply *reply = m_networkManager->get(request); + connect(reply, &QNetworkReply::finished, this, [reply, this] { + reply->deleteLater(); + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + // Check HTTP status code + if (status != 200 || reply->error() != QNetworkReply::NoError) { + qCWarning(dcDynatrace()) << "Request error:" << status << reply->errorString(); + emit connectionChanged(false); + return; + } + emit connectionChanged(true); + }); +} + +void Ufo::initBackgroundColor(bool top, bool bottom) +{ + QUrl url; + url.setScheme("http"); + url.setHost(m_address.toString()); + url.setPath("/api"); + QUrlQuery query; + if (top) { + query.addQueryItem("top_init", "0"); + } + if (bottom) { + query.addQueryItem("bottom_init", "0"); + } + url.setQuery(query); + QNetworkRequest request; + request.setUrl(url); + qCDebug(dcDynatrace()) << "Sending request" << url; + QNetworkReply *reply = m_networkManager->get(request); + connect(reply, &QNetworkReply::finished, this, [reply, this] { + reply->deleteLater(); + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + // Check HTTP status code + if (status != 200 || reply->error() != QNetworkReply::NoError) { + qCWarning(dcDynatrace()) << "Request error:" << status << reply->errorString(); + emit connectionChanged(false); + return; + } + emit connectionChanged(true); + }); +} + +void Ufo::setBackgroundColor(bool top, bool initTop, bool bottom, bool initBottom, QColor color) +{ + QUrl url; + url.setScheme("http"); + url.setHost(m_address.toString()); + url.setPath("/api"); + QUrlQuery query; + if (initTop){ + query.addQueryItem("top_init", "0"); + } + if (initBottom){ + query.addQueryItem("bottom_init", "0"); + } + if (top){ + query.addQueryItem("top_bg", color.name().remove(0,1)); + } + if (bottom) { + query.addQueryItem("bottom_bg", color.name().remove(0,1)); + } + url.setQuery(query); + QNetworkRequest request; + request.setUrl(url); + + qCDebug(dcDynatrace()) << "Sending request" << url; + QNetworkReply *reply = m_networkManager->get(request); + connect(reply, &QNetworkReply::finished, this, [reply, this] { + reply->deleteLater(); + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + // Check HTTP status code + if (status != 200 || reply->error() != QNetworkReply::NoError) { + qCWarning(dcDynatrace()) << "Request error:" << status << reply->errorString(); + emit connectionChanged(false); + return; + } + emit connectionChanged(true); + }); +} + +void Ufo::startWhirl(bool top, bool bottom, QColor color, int speed, bool clockwise) +{ + Q_UNUSED(clockwise) + QUrl url; + url.setScheme("http"); + url.setHost(m_address.toString()); + url.setPath("/api"); + QUrlQuery query; + if (top){ + query.addQueryItem("top_init", "0"); + query.addQueryItem("top_bg", color.name().remove(0,1)); + query.addQueryItem("top", "0|8|000000"); + query.addQueryItem("top_whirl", QString::number(speed)); + } + if (bottom) { + query.addQueryItem("bottom_init", "0"); + query.addQueryItem("bottom_bg", color.name().remove(0,1)); + query.addQueryItem("bottom", "0|8|000000"); + query.addQueryItem("bottom_whirl", QString::number(speed)); + } + url.setQuery(query); + QNetworkRequest request; + request.setUrl(url); + + qCDebug(dcDynatrace()) << "Sending request" << url; + QNetworkReply *reply = m_networkManager->get(request); + connect(reply, &QNetworkReply::finished, this, [reply, this] { + reply->deleteLater(); + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + // Check HTTP status code + if (status != 200 || reply->error() != QNetworkReply::NoError) { + qCWarning(dcDynatrace()) << "Request error:" << status << reply->errorString(); + emit connectionChanged(false); + return; + } + emit connectionChanged(true); + }); +} + +void Ufo::startMorph(bool top, bool bottom, QColor color, int time, int speed) +{ + QUrl url; + url.setScheme("http"); + url.setHost(m_address.toString()); + url.setPath("/api"); + QUrlQuery query; + if (top){ + query.addQueryItem("top_init", "0"); + query.addQueryItem("top_bg", color.name().remove(0,1)); + query.addQueryItem("top", "0|16|000000"); + query.addQueryItem("top_morph", QString::number(time)+"|"+QString::number(speed)); + } + if (bottom) { + query.addQueryItem("bottom_init", "0"); + query.addQueryItem("bottom_bg", color.name().remove(0,1)); + query.addQueryItem("bottom", "0|16|000000"); + query.addQueryItem("bottom_morph", QString::number(time)+"|"+QString::number(speed)); + } + url.setQuery(query); + QNetworkRequest request; + request.setUrl(url); + + qCDebug(dcDynatrace()) << "Sending request" << url; + QNetworkReply *reply = m_networkManager->get(request); + connect(reply, &QNetworkReply::finished, this, [reply, this] { + reply->deleteLater(); + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + // Check HTTP status code + if (status != 200 || reply->error() != QNetworkReply::NoError) { + qCWarning(dcDynatrace()) << "Request error:" << status << reply->errorString(); + emit connectionChanged(false); + return; + } + emit connectionChanged(true); + }); +} diff --git a/dynatrace/ufo.h b/dynatrace/ufo.h new file mode 100644 index 00000000..0d840ccc --- /dev/null +++ b/dynatrace/ufo.h @@ -0,0 +1,68 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +* +* Copyright 2013 - 2020, nymea GmbH +* Contact: contact@nymea.io +* +* This file is part of nymea. +* This project including source code and documentation is protected by +* copyright law, and remains the property of nymea GmbH. All rights, including +* reproduction, publication, editing and translation, are reserved. The use of +* this project is subject to the terms of a license agreement to be concluded +* with nymea GmbH in accordance with the terms of use of nymea GmbH, available +* under https://nymea.io/license +* +* GNU Lesser General Public License Usage +* Alternatively, this project may be redistributed and/or modified under the +* terms of the GNU Lesser General Public License as published by the Free +* Software Foundation; version 3. This project is distributed in the hope that +* it will be useful, but WITHOUT ANY WARRANTY; without even the implied +* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with this project. If not, see . +* +* For any further details and any questions please contact us under +* contact@nymea.io or see our FAQ/Licensing Information on +* https://nymea.io/license/faq +* +* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef DYNATRACE_UFO_H +#define DYNATRACE_UFO_H + +#include "network/networkaccessmanager.h" +#include "integrations/integrationplugin.h" + +#include +#include +#include +#include + +class Ufo : public QObject +{ + Q_OBJECT +public: + explicit Ufo(NetworkAccessManager *networkManager, const QHostAddress &address, QObject *parent = nullptr); + + void getId(); + void resetLogo(); + void setLogo(QColor led1, QColor led2, QColor led3, QColor led4); + void initBackgroundColor(bool top, bool bottom); + void setBackgroundColor(bool top, bool initTop, bool bottom, bool initBottom, QColor color); //top and bottom flags are to select the ring, init is to reset a effect + void setLeds(bool top, int ledIndex, int numOfLeds, QColor color); + void startWhirl(bool top, bool bottom, QColor color, int speed, bool clockwise); //Speed: 0 (no movement) to about 510 (very fast) + void stopWhirl(bool top, bool bottom); + void startMorph(bool top, bool bottom, QColor color, int time, int speed); //time in ms, speed 0-10 + void stopMorph(bool top, bool bottom); + +private: + NetworkAccessManager *m_networkManager; + QHostAddress m_address; + +signals: + void connectionChanged(bool reachable); + void idReceived(const QString &id); + +}; +#endif //DYNATRACE_UFO_H diff --git a/nymea-plugins.pro b/nymea-plugins.pro index 6ea6aacf..61ee4220 100644 --- a/nymea-plugins.pro +++ b/nymea-plugins.pro @@ -14,6 +14,7 @@ PLUGIN_DIRS = \ daylightsensor \ denon \ dweetio \ + dynatrace \ elgato \ elro \ eq-3 \