/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 * This project may also contain libraries licensed under the open source software license GNU GPL v.3. * 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 IntegrationPluginDynatrace::IntegrationPluginDynatrace() { } void IntegrationPluginDynatrace::discoverThings(ThingDiscoveryInfo *info) { if (info->thingClassId() == ufoThingClassId) { QHostInfo::lookupHost("ufo.home", this, [info](const QHostInfo &host){ if (host.error() != QHostInfo::NoError) { qCDebug(dcDynatrace()) << "Lookup failed:" << host.errorString(); } foreach (QHostAddress address, host.addresses()) { qCDebug(dcDynatrace()) << "Found IP address" << address.toString(); ThingDescriptor descriptor(ufoThingClassId, "Ufo", address.toString()); ParamList params; /*Thing *existingThing = myThings().findByParams(ParamList() << Param(ufoThingIdParamTypeId, "")); if (existingThing) { //For Thing re-discovery descriptor.setThingId(existingthing->id()); }*/ params << Param(ufoThingHostParamTypeId, address.toString()); descriptor.setParams(params); info->addThingDescriptor(descriptor); } info->finish(Thing::ThingErrorNoError); }); } } 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); } } } void IntegrationPluginDynatrace::postSetupThing(Thing *thing) { if (thing->thingClassId() == ufoThingClassId) { thing->setStateValue(ufoConnectedStateTypeId, true); //FIXME 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); 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]() { //TODO check if Thing is reachable }); } } 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) { Q_UNUSED(connected) }