/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 #include #include "integrationpluginws2812fx.h" #include "plugininfo.h" #include "nymealightserialinterface.h" IntegrationPluginWs2812fx ::IntegrationPluginWs2812fx () { } void IntegrationPluginWs2812fx::setupThing(ThingSetupInfo *info) { Thing *thing = info->thing(); if (thing->thingClassId() == nymeaLightSerialThingClassId) { QString interface = thing->paramValue(nymeaLightSerialThingSerialPortParamTypeId).toString(); if (m_usedInterfaces.contains(interface)) { info->finish(Thing::ThingErrorHardwareNotAvailable, QT_TR_NOOP("This serial port is already in use.")); return; } NymeaLightSerialInterface *lightInterface = new NymeaLightSerialInterface(interface, thing); NymeaLight *light = new NymeaLight(lightInterface, this); lightInterface->setParent(light); m_usedInterfaces.append(interface); m_lights.insert(thing, light); connect(light, &NymeaLight::availableChanged, thing, [=](bool available){ qCDebug(dcWs2812fx()) << thing << "available changed" << available; thing->setStateValue(nymeaLightSerialConnectedStateTypeId, available); if (available) { // Set the light to the current states light->setPower(thing->stateValue(nymeaLightSerialPowerStateTypeId).toBool()); light->setBrightness(thing->stateValue(nymeaLightSerialBrightnessStateTypeId).toUInt()); light->setColor(thing->stateValue(nymeaLightSerialColorStateTypeId).value()); light->setEffect(thing->stateValue(nymeaLightSerialEffectModeStateTypeId).toUInt()); light->setSpeed(thing->stateValue(nymeaLightSerialSpeedStateTypeId).toUInt()); } }); info->finish(Thing::ThingErrorNoError); } } void IntegrationPluginWs2812fx::postSetupThing(Thing *thing) { if (thing->thingClassId() == nymeaLightSerialThingClassId) { NymeaLight *light = m_lights.value(thing); light->enable(); } } void IntegrationPluginWs2812fx::discoverThings(ThingDiscoveryInfo *info) { // Create the list of available serial interfaces Q_FOREACH(QSerialPortInfo port, QSerialPortInfo::availablePorts()) { qCDebug(dcWs2812fx()) << "Found serial port:" << port.portName(); QString description = port.systemLocation() + " " + port.manufacturer() + " " + port.description(); ThingDescriptor descriptor(info->thingClassId(), QT_TR_NOOP("Nymea light"), description); foreach (Thing *existingThing, myThings().filterByParam(nymeaLightSerialThingSerialPortParamTypeId, port.systemLocation())) { descriptor.setThingId(existingThing->id()); } ParamList parameters; parameters.append(Param(nymeaLightSerialThingSerialPortParamTypeId, port.systemLocation())); descriptor.setParams(parameters); info->addThingDescriptor(descriptor); } info->finish(Thing::ThingErrorNoError); } void IntegrationPluginWs2812fx::executeAction(ThingActionInfo *info) { Thing *thing = info->thing(); Action action = info->action(); NymeaLight *light = m_lights.value(thing); if (!light || !light->available()) { info->finish(Thing::ThingErrorHardwareNotAvailable); return; } if (action.actionTypeId() == nymeaLightSerialPowerActionTypeId) { bool power = action.param(nymeaLightSerialPowerActionPowerParamTypeId).value().toBool(); qCDebug(dcWs2812fx()) << "Set power" << power; NymeaLightInterfaceReply *reply = light->setPower(power, 500); connect(info, &ThingActionInfo::aborted, reply, &NymeaLightInterfaceReply::finished); connect(reply, &NymeaLightInterfaceReply::finished, this, [=](){ if (reply->status() != NymeaLightInterface::StatusSuccess) { info->finish(Thing::ThingErrorHardwareFailure); return; } qCDebug(dcWs2812fx()) << "Set power finished successfully" << power; thing->setStateValue(nymeaLightSerialPowerStateTypeId, power); info->finish(Thing::ThingErrorNoError); }); } else if (action.actionTypeId() == nymeaLightSerialColorActionTypeId) { QColor color = action.param(nymeaLightSerialColorActionColorParamTypeId).value().value(); qCDebug(dcWs2812fx()) << "Set color to" << color.name(QColor::HexRgb); NymeaLightInterfaceReply *reply = light->setColor(color); connect(info, &ThingActionInfo::aborted, reply, &NymeaLightInterfaceReply::finished); connect(reply, &NymeaLightInterfaceReply::finished, this, [=](){ if (reply->status() != NymeaLightInterface::StatusSuccess) { info->finish(Thing::ThingErrorHardwareFailure); return; } qCDebug(dcWs2812fx()) << "Set color finished successfully" << color.name(QColor::HexRgb); thing->setStateValue(nymeaLightSerialColorStateTypeId, color); info->finish(Thing::ThingErrorNoError); }); } else if (action.actionTypeId() == nymeaLightSerialColorTemperatureActionTypeId) { // minValue 153, maxValue 500 uint colorTemperature = action.param(nymeaLightSerialColorTemperatureActionColorTemperatureParamTypeId).value().toDouble(); QColor color; color.setRgb(255, 255, qRound((255.00 - (((colorTemperature - 153.00) / 347.00)) * 255.00))); qCDebug(dcWs2812fx()) << "Set color temperature" << colorTemperature << color.name(QColor::HexRgb); NymeaLightInterfaceReply *reply = light->setColor(color); connect(info, &ThingActionInfo::aborted, reply, &NymeaLightInterfaceReply::finished); connect(reply, &NymeaLightInterfaceReply::finished, this, [=](){ if (reply->status() != NymeaLightInterface::StatusSuccess) { info->finish(Thing::ThingErrorHardwareFailure); return; } qCDebug(dcWs2812fx()) << "Set color temperature finished successfully" << colorTemperature; thing->setStateValue(nymeaLightSerialColorTemperatureStateTypeId, colorTemperature); info->finish(Thing::ThingErrorNoError); }); } else if (action.actionTypeId() == nymeaLightSerialBrightnessActionTypeId) { quint8 brightnessPercentage = action.param(nymeaLightSerialBrightnessActionBrightnessParamTypeId).value().toUInt(); quint8 brightness = qRound(255.0 * brightnessPercentage / 100); qCDebug(dcWs2812fx()) << "Set brightness to" << brightnessPercentage << brightness; NymeaLightInterfaceReply *reply = light->setBrightness(brightness, 1000); connect(info, &ThingActionInfo::aborted, reply, &NymeaLightInterfaceReply::finished); connect(reply, &NymeaLightInterfaceReply::finished, this, [=](){ if (reply->status() != NymeaLightInterface::StatusSuccess) { info->finish(Thing::ThingErrorHardwareFailure); return; } qCDebug(dcWs2812fx()) << "Set brightness finished successfully" << brightness; thing->setStateValue(nymeaLightSerialBrightnessStateTypeId, brightnessPercentage); info->finish(Thing::ThingErrorNoError); }); } else if (action.actionTypeId() == nymeaLightSerialSpeedActionTypeId) { quint16 speedPercentage = action.param(nymeaLightSerialSpeedActionSpeedParamTypeId).value().toUInt(); quint16 speed = 2000 - (speedPercentage * 20); qCDebug(dcWs2812fx()) << "Set speed" << speedPercentage << "%" << speed << "ms"; NymeaLightInterfaceReply *reply = light->setSpeed(speed); connect(info, &ThingActionInfo::aborted, reply, &NymeaLightInterfaceReply::finished); connect(reply, &NymeaLightInterfaceReply::finished, this, [=](){ if (reply->status() != NymeaLightInterface::StatusSuccess) { info->finish(Thing::ThingErrorHardwareFailure); return; } qCDebug(dcWs2812fx()) << "Set speed finished successfully" << speedPercentage << "%" << speed << "ms"; thing->setStateValue(nymeaLightSerialSpeedStateTypeId, speedPercentage); info->finish(Thing::ThingErrorNoError); }); } else if (action.actionTypeId() == nymeaLightSerialEffectModeActionTypeId) { QString effectMode = action.param(nymeaLightSerialEffectModeActionEffectModeParamTypeId).value().toString(); quint8 mode = FX_MODE_STATIC; if (effectMode == "Static") { mode = FX_MODE_STATIC; } else if (effectMode == "Blink") { mode = FX_MODE_BLINK; } else if (effectMode == "Color Wipe") { mode = FX_MODE_COLOR_WIPE; } else if (effectMode == "Color Wipe Inverse") { mode = FX_MODE_COLOR_WIPE_INV; } else if (effectMode == "Color Wipe Reverse") { mode = FX_MODE_COLOR_WIPE_REV; } else if (effectMode == "Color Wipe Reverse Inverse") { mode = FX_MODE_COLOR_WIPE_REV_INV; } else if (effectMode == "Color Wipe Random") { mode = FX_MODE_COLOR_WIPE_RANDOM; } else if (effectMode == "Random Color") { mode = FX_MODE_RANDOM_COLOR; } else if (effectMode == "Single Dynamic") { mode = FX_MODE_SINGLE_DYNAMIC; } else if (effectMode == "Multi Dynamic") { mode = FX_MODE_MULTI_DYNAMIC; } else if (effectMode == "Rainbow") { mode = FX_MODE_RAINBOW; } else if (effectMode == "Rainbow Cycle") { mode = FX_MODE_RAINBOW_CYCLE; } else if (effectMode == "Scan") { mode = FX_MODE_SCAN; } else if (effectMode == "Dual Scan") { mode = FX_MODE_DUAL_SCAN; } else if (effectMode == "Fade") { mode = FX_MODE_FADE; } else if (effectMode == "Theater Chase") { mode = FX_MODE_THEATER_CHASE; } else if (effectMode == "Theater Chase Rainbow") { mode = FX_MODE_THEATER_CHASE_RAINBOW; } else if (effectMode == "Running Lights") { mode = FX_MODE_RUNNING_LIGHTS; } else if (effectMode == "Twinkle") { mode = FX_MODE_TWINKLE; } else if (effectMode == "Twinkle Random") { mode = FX_MODE_TWINKLE_RANDOM; } else if (effectMode == "Twinkle Fade") { mode = FX_MODE_TWINKLE_FADE; } else if (effectMode == "Twinkle Fade Random") { mode = FX_MODE_TWINKLE_FADE_RANDOM; } else if (effectMode == "Sparkle") { mode = FX_MODE_SPARKLE; } else if (effectMode == "Flash Sparkle") { mode = FX_MODE_FLASH_SPARKLE; } else if (effectMode == "Hyper Sparkle") { mode = FX_MODE_HYPER_SPARKLE; } else if (effectMode == "Strobe") { mode = FX_MODE_STROBE; } else if (effectMode == "Strobe Rainbow") { mode = FX_MODE_STROBE_RAINBOW; } else if (effectMode == "Multi Strobe") { mode = FX_MODE_MULTI_STROBE; } else if (effectMode == "Blink Rainbow") { mode = FX_MODE_BLINK_RAINBOW; } else if (effectMode == "Chase White") { mode = FX_MODE_CHASE_WHITE; } else if (effectMode == "Chase Color") { mode = FX_MODE_CHASE_COLOR; } else if (effectMode == "Chase Random") { mode = FX_MODE_CHASE_RANDOM; } else if (effectMode == "Chase Flash") { mode = FX_MODE_CHASE_FLASH; } else if (effectMode == "Chase Flash Random") { mode = FX_MODE_CHASE_FLASH_RANDOM; } else if (effectMode == "Chase Rainbow White") { mode = FX_MODE_CHASE_RAINBOW_WHITE; } else if (effectMode == "Chase Blackout") { mode = FX_MODE_CHASE_BLACKOUT; } else if (effectMode == "Chase Blackout Rainbow") { mode = FX_MODE_CHASE_BLACKOUT_RAINBOW; } else if (effectMode == "Color Sweep Random") { mode = FX_MODE_COLOR_SWEEP_RANDOM; } else if (effectMode == "Running Color") { mode = FX_MODE_RUNNING_COLOR; } else if (effectMode == "Running Red Blue") { mode = FX_MODE_RUNNING_RED_BLUE; } else if (effectMode == "Running Random") { mode = FX_MODE_RUNNING_RANDOM; }else if (effectMode == "Larson Scanner") { mode = FX_MODE_LARSON_SCANNER; }else if (effectMode == "Comet") { mode = FX_MODE_COMET; }else if (effectMode == "Fireworks") { mode = FX_MODE_FIREWORKS; }else if (effectMode == "Fireworks Random") { mode = FX_MODE_FIREWORKS_RANDOM; }else if (effectMode == "Merry Christmas") { mode = FX_MODE_MERRY_CHRISTMAS; }else if (effectMode == "Fire Flicker") { mode = FX_MODE_FIRE_FLICKER; }else if (effectMode == "Fire Flicker (soft)") { mode = FX_MODE_FIRE_FLICKER_SOFT; }else if (effectMode == "Fire Flicker (intense)") { mode = FX_MODE_FIRE_FLICKER_INTENSE; }else if (effectMode == "Circus Combustus") { mode = FX_MODE_CIRCUS_COMBUSTUS; }else if (effectMode == "Halloween") { mode = FX_MODE_HALLOWEEN; }else if (effectMode == "Bicolor Chase") { mode = FX_MODE_BICOLOR_CHASE; }else if (effectMode == "Tricolor Chase") { mode = FX_MODE_TRICOLOR_CHASE; }else if (effectMode == "ICU") { mode = FX_MODE_ICU; }else if (effectMode == "Custom 0") { mode = FX_MODE_CUSTOM_0; }else if (effectMode == "Custom 1") { mode = FX_MODE_CUSTOM_1; }else if (effectMode == "Custom 2") { mode = FX_MODE_CUSTOM_2; }else if (effectMode == "Custom 3") { mode = FX_MODE_CUSTOM_3; } qCDebug(dcWs2812fx()) << "Set mode" << effectMode << mode; NymeaLightInterfaceReply *reply = light->setEffect(mode); connect(info, &ThingActionInfo::aborted, reply, &NymeaLightInterfaceReply::finished); connect(reply, &NymeaLightInterfaceReply::finished, this, [=](){ if (reply->status() != NymeaLightInterface::StatusSuccess) { info->finish(Thing::ThingErrorHardwareFailure); return; } qCDebug(dcWs2812fx()) << "Set mode finished successfully" << effectMode << mode; thing->setStateValue(nymeaLightSerialEffectModeStateTypeId, effectMode); info->finish(Thing::ThingErrorNoError); }); } } void IntegrationPluginWs2812fx::thingRemoved(Thing *thing) { if (thing->thingClassId() == nymeaLightSerialThingClassId) { m_usedInterfaces.removeAll(thing->paramValue(nymeaLightSerialThingSerialPortParamTypeId).toString()); NymeaLight *light = m_lights.take(thing); light->deleteLater(); } }