From f333d67358115f325eabb8e5708c448321cdab1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Fri, 12 Apr 2024 16:15:16 +0200 Subject: [PATCH] Remove boblight plugin --- boblight/README.md | 34 -- boblight/bobchannel.cpp | 99 ------ boblight/bobchannel.h | 76 ----- boblight/bobclient.cpp | 191 ----------- boblight/bobclient.h | 88 ------ boblight/boblight.png | Bin 44846 -> 0 bytes boblight/boblight.pro | 20 -- boblight/integrationpluginboblight.cpp | 297 ------------------ boblight/integrationpluginboblight.h | 78 ----- boblight/integrationpluginboblight.json | 138 -------- boblight/meta.json | 13 - ...71bea-1362-4cc6-888f-2ebe80bad46a-en_US.ts | 154 --------- debian/control | 14 +- debian/nymea-plugin-boblight.install.in | 2 - nymea-plugins.pro | 1 - 15 files changed, 1 insertion(+), 1204 deletions(-) delete mode 100644 boblight/README.md delete mode 100644 boblight/bobchannel.cpp delete mode 100644 boblight/bobchannel.h delete mode 100644 boblight/bobclient.cpp delete mode 100644 boblight/bobclient.h delete mode 100644 boblight/boblight.png delete mode 100644 boblight/boblight.pro delete mode 100644 boblight/integrationpluginboblight.cpp delete mode 100644 boblight/integrationpluginboblight.h delete mode 100644 boblight/integrationpluginboblight.json delete mode 100644 boblight/meta.json delete mode 100644 boblight/translations/d5271bea-1362-4cc6-888f-2ebe80bad46a-en_US.ts delete mode 100644 debian/nymea-plugin-boblight.install.in diff --git a/boblight/README.md b/boblight/README.md deleted file mode 100644 index 8e117ad7..00000000 --- a/boblight/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# Boblight - -This plugin allows to communicate with a [Boblight server](https://code.google.com/p/boblight/) - -The boblight server needs to be installed and running. In nymea it is required to setup the Boblight server connection first, during the setup you can configure how many channels you want to add. Each channel will appear auotamtically as an own device insided nymea. Default configuration for the Boblight server is `localhost:19333`, you can change the parameters during device setup. - -Once the Boblight devices are added you can control them like any other color light in nymea. - - -## Supported Things - -* Boblight Server - * Gateway device - * Define channel count -* Boblight Channel - * Color light - * Set color - * Set color temperature - * Set brightness - * Set power - -**Generall** - -* No internet connection required - -## Requirements - -* Boblight server running on `localhost:19333` or any other reachable IP address. -* Boblight device connected to the Boblight server. -* The package "nymea-plugin-boblight" must be installed. - -## More - -For more information regarding the project please visit the [project site](https://sites.google.com/site/wikikrautbox/krautbox/hardware/boblight). diff --git a/boblight/bobchannel.cpp b/boblight/bobchannel.cpp deleted file mode 100644 index 2e96280e..00000000 --- a/boblight/bobchannel.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* 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 "bobchannel.h" - -BobChannel::BobChannel(const int &id, QObject *parent) : - QObject(parent), - m_id(id) -{ - m_animation = new QPropertyAnimation(this, "finalColor", this); - m_animation->setDuration(500); -} - -int BobChannel::id() const -{ - return m_id; -} - -QColor BobChannel::color() const -{ - return m_color; -} - -void BobChannel::setColor(const QColor &color) -{ - if (m_animation->state() == QPropertyAnimation::Running) { - m_animation->stop(); - m_finalColor = m_color; - } - - m_color = color; - emit colorChanged(); - - m_animation->setStartValue(m_finalColor); - m_animation->setEndValue(color); - m_animation->start(); -} - -bool BobChannel::power() const -{ - return m_power; -} - -void BobChannel::setPower(bool power) -{ - if (power != m_power) { - m_power = power; - emit powerChanged(); - - if (m_animation->state() == QPropertyAnimation::Running) { - m_animation->stop(); - } - - QColor target = m_color; - target.setAlpha(target.alpha() * (m_power ? 1 : 0)); - m_animation->setStartValue(m_finalColor); - m_animation->setEndValue(target); - m_animation->start(); - } -} - -QColor BobChannel::finalColor() const -{ - return m_finalColor; -} - -void BobChannel::setFinalColor(const QColor &color) -{ - m_finalColor = color; - emit finalColorChanged(); -} - diff --git a/boblight/bobchannel.h b/boblight/bobchannel.h deleted file mode 100644 index 4bda1627..00000000 --- a/boblight/bobchannel.h +++ /dev/null @@ -1,76 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* 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 BOBCHANNEL_H -#define BOBCHANNEL_H - -#include -#include -#include - -class BobChannel : public QObject -{ - Q_OBJECT - Q_PROPERTY(bool power READ power WRITE setPower NOTIFY powerChanged) - Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) - - // don't directly write to this, the propertyAnimation requires a writable property tho... - Q_PROPERTY(QColor finalColor READ finalColor WRITE setFinalColor NOTIFY finalColorChanged) - -public: - explicit BobChannel(const int &id, QObject *parent = 0); - - int id() const; - - QColor color() const; - void setColor(const QColor &color); - - bool power() const; - void setPower(bool power); - - QColor finalColor() const; - void setFinalColor(const QColor &color); - -private: - QPropertyAnimation *m_animation; - int m_id; - bool m_power = false; - QColor m_color = Qt::white; - QColor m_finalColor = Qt::black; - -signals: - void colorChanged(); - void brightnessChanged(); - void finalColorChanged(); - void powerChanged(); - -}; - -#endif // BOBCHANNEL_H diff --git a/boblight/bobclient.cpp b/boblight/bobclient.cpp deleted file mode 100644 index 8441cd7f..00000000 --- a/boblight/bobclient.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* 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 "bobclient.h" -#include "extern-plugininfo.h" - -#include "libboblight/boblight.h" - -#include -#include - -BobClient::BobClient(const QString &host, const int &port, QObject *parent) : - QObject(parent), - m_host(host), - m_port(port), - m_connected(false) -{ - m_syncTimer = new QTimer(this); - m_syncTimer->setSingleShot(false); - m_syncTimer->setInterval(25); - - connect(m_syncTimer, SIGNAL(timeout()), this, SLOT(sync())); -} - -BobClient::~BobClient() -{ - if (m_boblight) { - boblight_destroy(m_boblight); - } -} - -bool BobClient::connectToBoblight() -{ - if (connected()) { - return true; - } - m_boblight = boblight_init(); - - //try to connect, if we can't then bitch to stderr and destroy boblight - if (!boblight_connect(m_boblight, m_host.toLatin1().data(), m_port, 1000000)) { - qCWarning(dcBoblight) << "Failed to connect:" << boblight_geterror(m_boblight); - boblight_destroy(m_boblight); - m_boblight = nullptr; - setConnected(false); - return false; - } - - qCDebug(dcBoblight) << "Connected to boblightd successfully."; - boblight_setpriority(m_boblight, m_priority); - for (int i = 0; i < lightsCount(); ++i) { - BobChannel *channel = new BobChannel(i, this); - channel->setColor(QColor(255,255,255,0)); - connect(channel, SIGNAL(colorChanged()), this, SLOT(sync())); - m_channels.insert(i, channel); - } - setConnected(true); - return true; -} - -bool BobClient::connected() -{ - return m_connected; -} - -void BobClient::setPriority(int priority) -{ - m_priority = priority; - if (connected()) { - qCDebug(dcBoblight) << "setting priority to" << priority; - boblight_setpriority(m_boblight, priority); - } - emit priorityChanged(priority); -} - -void BobClient::setPower(int channel, bool power) -{ - qCDebug(dcBoblight()) << "BobClient: setPower" << channel << power; - m_channels.value(channel)->setPower(power); - emit powerChanged(channel, power); -} - -BobChannel *BobClient::getChannel(const int &id) -{ - foreach (BobChannel *channel, m_channels) { - if (channel->id() == id) - return channel; - } - return nullptr; -} - -void BobClient::setColor(int channel, QColor color) -{ - if (channel == -1) { - for (int i = 0; i < lightsCount(); ++i) { - setColor(i, color); - } - } else { - BobChannel *c = getChannel(channel); - if (c) { - c->setColor(color); - qCDebug(dcBoblight) << "set channel" << channel << "to color" << color; - emit colorChanged(channel, color); - } - } -} - -void BobClient::setBrightness(int channel, int brightness) -{ - QColor color = m_channels.value(channel)->color(); - color.setAlpha(qRound(brightness * 255.0 / 100)); - m_channels.value(channel)->setColor(color); - emit brightnessChanged(channel, brightness); - - if (brightness > 0) { - m_channels.value(channel)->setPower(true); - emit powerChanged(channel, true); - } -} - -void BobClient::sync() -{ - if (!m_connected) - return; - - foreach (BobChannel *channel, m_channels) { - int rgb[3]; - rgb[0] = channel->finalColor().red() * channel->finalColor().alphaF(); - rgb[1] = channel->finalColor().green() * channel->finalColor().alphaF(); - rgb[2] = channel->finalColor().blue() * channel->finalColor().alphaF(); - boblight_addpixel(m_boblight, channel->id(), rgb); - } - - if (!boblight_sendrgb(m_boblight, 1, nullptr)) { - qCWarning(dcBoblight) << "Boblight connection error:" << boblight_geterror(m_boblight); - boblight_destroy(m_boblight); - qDeleteAll(m_channels); - m_channels.clear(); - setConnected(false); - } -} - -void BobClient::setConnected(bool connected) -{ - m_connected = connected; - emit connectionChanged(); - - // if disconnected, delete all channels - if (!connected) { - m_syncTimer->stop(); - qDeleteAll(m_channels); - } else { - m_syncTimer->start(); - } -} - -int BobClient::lightsCount() -{ - return boblight_getnrlights(m_boblight); -} - -QColor BobClient::currentColor(const int &channel) -{ - return getChannel(channel)->color(); -} diff --git a/boblight/bobclient.h b/boblight/bobclient.h deleted file mode 100644 index 2f29ac4c..00000000 --- a/boblight/bobclient.h +++ /dev/null @@ -1,88 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* 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 BOBCLIENT_H -#define BOBCLIENT_H - -#include -#include -#include -#include -#include - -#include - -class BobClient : public QObject -{ - Q_OBJECT -public: - explicit BobClient(const QString &host = "127.0.0.1", const int &port = 19333, QObject *parent = nullptr); - ~BobClient(); - - bool connectToBoblight(); - bool connected(); - - int lightsCount(); - QColor currentColor(const int &channel); - - void setPriority(int priority); - - void setPower(int channel, bool power); - void setColor(int channel, QColor color); - void setBrightness(int channel, int brightness); - -private: - void *m_boblight = nullptr; - - QTimer *m_syncTimer; - QString m_host; - int m_port; - bool m_connected; - int m_priority = 128; - - QMap m_colors; - QMap m_channels; - - BobChannel *getChannel(const int &id); - - -private slots: - void sync(); - void setConnected(bool connected); - -signals: - void connectionChanged(); - void powerChanged(int channel, bool power); - void brightnessChanged(int channel, int brightness); - void colorChanged(int channel, const QColor &color); - void priorityChanged(int priority); -}; - -#endif // BOBCLIENT_H diff --git a/boblight/boblight.png b/boblight/boblight.png deleted file mode 100644 index acee03d021dcd26c015bd28de4d956f9c59a0800..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44846 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 diff --git a/boblight/boblight.pro b/boblight/boblight.pro deleted file mode 100644 index 70c58d36..00000000 --- a/boblight/boblight.pro +++ /dev/null @@ -1,20 +0,0 @@ -include(../plugins.pri) - -QT += dbus bluetooth concurrent - -CONFIG += c++11 - -TARGET = $$qtLibraryTarget(nymea_integrationpluginboblight) -LIBS += -lboblight - -SOURCES += \ - integrationpluginboblight.cpp \ - bobclient.cpp \ - bobchannel.cpp - -HEADERS += \ - integrationpluginboblight.h \ - bobclient.h \ - bobchannel.h - - diff --git a/boblight/integrationpluginboblight.cpp b/boblight/integrationpluginboblight.cpp deleted file mode 100644 index 86af2e6a..00000000 --- a/boblight/integrationpluginboblight.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* 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 "integrationpluginboblight.h" - -#include "integrations/thing.h" - -#include "bobclient.h" -#include "plugininfo.h" -#include "plugintimer.h" - -#include -#include -#include - -IntegrationPluginBoblight::IntegrationPluginBoblight() -{ -} - -void IntegrationPluginBoblight::init() -{ - m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(15); - connect(m_pluginTimer, &PluginTimer::timeout, this, &IntegrationPluginBoblight::guhTimer); -} - -void IntegrationPluginBoblight::thingRemoved(Thing *thing) -{ - BobClient *client = m_bobClients.take(thing->id()); - if (thing->thingClassId() == boblightServerThingClassId) { - client->deleteLater(); - } -} - -void IntegrationPluginBoblight::startMonitoringAutoThings() -{ - m_canCreateAutoDevices = true; - qCDebug(dcBoblight()) << "Populating auto devices" << myThings().count(); - QHash parentDevices; - QHash deviceIds; - foreach (Thing *thing, myThings()) { - deviceIds.insert(thing->id(), thing); - if (thing->thingClassId() == boblightServerThingClassId) { -// qWarning() << "Device" << thing->id() << "is bridge"; - if (!parentDevices.contains(thing->id())) { - parentDevices[thing->id()] = 0; - } - } else if (thing->thingClassId() == boblightThingClassId) { -// qWarning() << "Device" << thing->id() << "is child to bridge" << thing->parentId(); - parentDevices[thing->parentId()] += 1; - } - } - QList descriptors; - foreach (const ThingId &id, parentDevices.keys()) { - if (parentDevices.value(id) < deviceIds.value(id)->paramValue(boblightServerThingChannelsParamTypeId).toInt()) { - for (int i = parentDevices.value(id); i < deviceIds.value(id)->paramValue(boblightServerThingChannelsParamTypeId).toInt(); i++) { - ThingDescriptor descriptor(boblightThingClassId, deviceIds.value(id)->name() + " " + QString::number(i + 1), QString(), id); - descriptor.setParams(ParamList() << Param(boblightThingChannelParamTypeId, i)); - qCDebug(dcBoblight()) << "Adding new boblight channel" << i + 1; - descriptors.append(descriptor); - } - } - } - if (!descriptors.isEmpty()) { - emit autoThingsAppeared(descriptors); - } -} - -void IntegrationPluginBoblight::guhTimer() -{ - foreach (BobClient *client, m_bobClients) { - if (!client->connected()) { - client->connectToBoblight(); - } - } -} - -void IntegrationPluginBoblight::onPowerChanged(int channel, bool power) -{ - qCDebug(dcBoblight()) << "power changed" << channel << power; - BobClient *sndr = dynamic_cast(sender()); - foreach (Thing* thing, myThings()) { - if (m_bobClients.value(thing->parentId()) == sndr && thing->paramValue(boblightThingChannelParamTypeId).toInt() == channel) { - qCDebug(dcBoblight()) << "setting state power" << power; - thing->setStateValue(boblightPowerStateTypeId, power); - } - } -} - -void IntegrationPluginBoblight::onBrightnessChanged(int channel, int brightness) -{ - BobClient *sndr = dynamic_cast(sender()); - foreach (Thing* thing, myThings()) { - if (m_bobClients.value(thing->parentId()) == sndr && thing->paramValue(boblightThingChannelParamTypeId).toInt() == channel) { - thing->setStateValue(boblightBrightnessStateTypeId, brightness); - } - } -} - -void IntegrationPluginBoblight::onColorChanged(int channel, const QColor &color) -{ - BobClient *sndr = dynamic_cast(sender()); - foreach (Thing* thing, myThings()) { - if (m_bobClients.value(thing->parentId()) == sndr && thing->paramValue(boblightThingChannelParamTypeId).toInt() == channel) { - thing->setStateValue(boblightColorStateTypeId, color); - } - } -} - -void IntegrationPluginBoblight::onPriorityChanged(int priority) -{ - BobClient *sndr = dynamic_cast(sender()); - foreach (Thing* thing, myThings()) { - if (thing->thingClassId() == boblightServerThingClassId && m_bobClients.value(thing->id()) == sndr) { - thing->setStateValue(boblightServerPriorityStateTypeId, priority); - } - } -} - -QColor IntegrationPluginBoblight::tempToRgb(int temp) -{ - // 153 cold: 0.839216, 1, 0.827451 - // 500 warm: 0.870588, 1, 0.266667 - - // => 0 : 214,255,212 - // 100 : 222,255,67 - - // r => 0 : 214 = 100 : 222 - // => temp : (x-214) = 100 : (255 - 214) - // => x = temp * (255-214) / 100 - // r = x + 214 - - int red = temp * 41 / 100 + 214; - - int green = 255; - - // b => 0 : 212 = 100 : 67 - // => temp : (212 - x) = 100 : (212 - 145) - // => x = temp * 145 / 100 - // g = 212 - x - - int blue = 212 - temp * 145 / 100; - - qWarning() << "temp:" << temp << "rgb" << red << green << blue; - return QColor(red, green, blue); -} - -void IntegrationPluginBoblight::setupThing(ThingSetupInfo *info) -{ - Thing *thing = info->thing(); - - if (thing->thingClassId() == boblightServerThingClassId) { - - BobClient *bobClient = new BobClient(thing->paramValue(boblightServerThingHostAddressParamTypeId).toString(), thing->paramValue(boblightServerThingPortParamTypeId).toInt(), this); - bool connected = bobClient->connectToBoblight(); - if (!connected) { - qCWarning(dcBoblight()) << "Error connecting to boblight on" << thing->paramValue(boblightServerThingHostAddressParamTypeId).toString(); - } else { - qCDebug(dcBoblight()) << "Connected to boblight"; - } - bobClient->setPriority(thing->stateValue(boblightServerPriorityStateTypeId).toInt()); - thing->setStateValue(boblightServerConnectedStateTypeId, connected); - m_bobClients.insert(thing->id(), bobClient); - connect(bobClient, &BobClient::connectionChanged, this, &IntegrationPluginBoblight::onConnectionChanged); - connect(bobClient, &BobClient::powerChanged, this, &IntegrationPluginBoblight::onPowerChanged); - connect(bobClient, &BobClient::brightnessChanged, this, &IntegrationPluginBoblight::onBrightnessChanged); - connect(bobClient, &BobClient::colorChanged, this, &IntegrationPluginBoblight::onColorChanged); - connect(bobClient, &BobClient::priorityChanged, this, &IntegrationPluginBoblight::onPriorityChanged); - } else if (thing->thingClassId() == boblightThingClassId) { - BobClient *bobClient = m_bobClients.value(thing->parentId()); - thing->setStateValue(boblightConnectedStateTypeId, bobClient->connected()); - m_bobClients.insert(thing->id(), bobClient); - } - - info->finish(Thing::ThingErrorNoError); -} - -void IntegrationPluginBoblight::postSetupThing(Thing *thing) -{ - if (thing->thingClassId() == boblightServerThingClassId && m_canCreateAutoDevices) { - startMonitoringAutoThings(); - } - if (thing->thingClassId() == boblightThingClassId) { - BobClient *bobClient = m_bobClients.value(thing->parentId()); - if (bobClient && bobClient->connected()) { - thing->setStateValue(boblightConnectedStateTypeId, bobClient->connected()); - - QColor color = thing->stateValue(boblightColorStateTypeId).value(); - int brightness = thing->stateValue(boblightBrightnessStateTypeId).toInt(); - bool power = thing->stateValue(boblightPowerStateTypeId).toBool(); - - bobClient->setColor(thing->paramValue(boblightThingChannelParamTypeId).toInt(), color); - bobClient->setBrightness(thing->paramValue(boblightThingChannelParamTypeId).toInt(), brightness); - bobClient->setPower(thing->paramValue(boblightThingChannelParamTypeId).toInt(), power); - - } - } -} - -void IntegrationPluginBoblight::executeAction(ThingActionInfo *info) -{ - Thing *thing = info->thing(); - Action action = info->action(); - - qCDebug(dcBoblight()) << "Execute action for boblight" << action.params(); - if (thing->thingClassId() == boblightServerThingClassId) { - BobClient *bobClient = m_bobClients.value(thing->id()); - if (!bobClient || !bobClient->connected()) { - qCWarning(dcBoblight()) << "Boblight on" << thing->paramValue(boblightServerThingHostAddressParamTypeId).toString() << "not connected"; - info->finish(Thing::ThingErrorHardwareNotAvailable); - return; - } - - if (action.actionTypeId() == boblightServerPriorityActionTypeId) { - bobClient->setPriority(action.param(boblightServerPriorityActionPriorityParamTypeId).value().toInt()); - info->finish(Thing::ThingErrorNoError); - return; - } - qCWarning(dcBoblight()) << "Unhandled action" << action.actionTypeId() << "for BoblightServer" << info; - info->finish(Thing::ThingErrorActionTypeNotFound); - return; - } - - if (thing->thingClassId() == boblightThingClassId) { - BobClient *bobClient = m_bobClients.value(thing->parentId()); - if (!bobClient || !bobClient->connected()) { - qCWarning(dcBoblight()) << "Boblight not connected"; - info->finish(Thing::ThingErrorHardwareNotAvailable); - return; - } - - if (action.actionTypeId() == boblightPowerActionTypeId) { - bobClient->setPower(thing->paramValue(boblightThingChannelParamTypeId).toInt(), action.param(boblightPowerActionPowerParamTypeId).value().toBool()); - info->finish(Thing::ThingErrorNoError); - return; - } - if (action.actionTypeId() == boblightColorActionTypeId) { - bobClient->setColor(thing->paramValue(boblightThingChannelParamTypeId).toInt(), action.param(boblightColorActionColorParamTypeId).value().value()); - info->finish(Thing::ThingErrorNoError); - return; - } - if (action.actionTypeId() == boblightBrightnessActionTypeId) { - bobClient->setBrightness(thing->paramValue(boblightThingChannelParamTypeId).toInt(), action.param(boblightBrightnessActionBrightnessParamTypeId).value().toInt()); - info->finish(Thing::ThingErrorNoError); - return; - } - if (action.actionTypeId() == boblightColorTemperatureActionTypeId) { - bobClient->setColor(thing->paramValue(boblightThingChannelParamTypeId).toInt(), tempToRgb(action.param(boblightColorTemperatureActionColorTemperatureParamTypeId).value().toInt())); - info->finish(Thing::ThingErrorNoError); - return; - } - info->finish(Thing::ThingErrorActionTypeNotFound); - return; - } - info->finish(Thing::ThingErrorThingClassNotFound); -} - -void IntegrationPluginBoblight::onConnectionChanged() -{ - BobClient *bobClient = static_cast(sender()); - qCDebug(dcBoblight()) << "Connection changed. BobClient:" << bobClient << bobClient->connected() << m_bobClients.keys(bobClient); - foreach (const ThingId &thingId, m_bobClients.keys(bobClient)) { - foreach (Thing *thing, myThings()) { - if (thing->id() == thingId || thing->parentId() == thingId) { - thing->setStateValue(boblightConnectedStateTypeId, bobClient->connected()); - break; - } - } - } -} - diff --git a/boblight/integrationpluginboblight.h b/boblight/integrationpluginboblight.h deleted file mode 100644 index 2654cf5f..00000000 --- a/boblight/integrationpluginboblight.h +++ /dev/null @@ -1,78 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -* -* 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 INTEGRATIONPLUGINBOBLIGHT_H -#define INTEGRATIONPLUGINBOBLIGHT_H - -#include "integrations/integrationplugin.h" -#include "bobclient.h" - -class BobClient; -class PluginTimer; - -class IntegrationPluginBoblight : public IntegrationPlugin -{ - Q_OBJECT - - Q_PLUGIN_METADATA(IID "io.nymea.IntegrationPlugin" FILE "integrationpluginboblight.json") - Q_INTERFACES(IntegrationPlugin) - -public: - explicit IntegrationPluginBoblight(); - - void init() override; - - void setupThing(ThingSetupInfo *info) override; - void postSetupThing(Thing *thing) override; - void thingRemoved(Thing *thing) override; - - void startMonitoringAutoThings() override; - - void executeAction(ThingActionInfo *info) override; - -private slots: - void onConnectionChanged(); - void guhTimer(); - - void onPowerChanged(int channel, bool power); - void onBrightnessChanged(int channel, int brightness); - void onColorChanged(int channel, const QColor &color); - void onPriorityChanged(int priority); - -private: - QColor tempToRgb(int temp); -private: - PluginTimer *m_pluginTimer = nullptr; - - QHash m_bobClients; - bool m_canCreateAutoDevices = false; -}; - -#endif // INTEGRATIONPLUGINBOBLIGHT_H diff --git a/boblight/integrationpluginboblight.json b/boblight/integrationpluginboblight.json deleted file mode 100644 index 19dab5fa..00000000 --- a/boblight/integrationpluginboblight.json +++ /dev/null @@ -1,138 +0,0 @@ -{ - "id": "d5271bea-1362-4cc6-888f-2ebe80bad46a", - "name": "Boblight", - "displayName": "Boblight", - "vendors": [ - { - "id": "f0c9dd91-c2b0-4cd0-b161-a17fee9d2303", - "name": "boblight", - "displayName": "Boblight", - "thingClasses": [ - { - "id": "f267a7f4-ed75-4026-9b97-98884d7f4399", - "name": "boblightServer", - "displayName": "Boblight server", - "createMethods": ["user"], - "interfaces": ["gateway", "connectable"], - "paramTypes": [ - { - "id": "de82ea8c-2f1e-4b93-b85a-f6a0b7f87e4a", - "name": "hostAddress", - "displayName": "Host Address", - "type" : "QString", - "inputType": "IPv4Address", - "defaultValue": "127.0.0.1" - }, - { - "id": "8cbe5ef8-6b45-441e-9051-08d48f3948da", - "name": "port", - "displayName": "Port", - "type" : "int", - "defaultValue": 19333 - }, - { - "id": "277f2458-d932-4a6e-a7bb-58814ab99663", - "name": "channels", - "displayName": "Channels", - "type": "int", - "defaultValue": 1 - } - ], - "stateTypes": [ - { - "id": "638fb9ec-4797-4ef6-a9b6-d935f1c49e17", - "name": "connected", - "displayName": "connected", - "displayNameEvent": "Connected changed", - "defaultValue": false, - "type": "bool" - }, - { - "id": "60d345e8-757c-4bc2-a96b-31121fc84356", - "name": "priority", - "displayName": "Priority", - "displayNameEvent": "Priority changed", - "displayNameAction": "Set priority", - "type": "int", - "defaultValue": 128, - "minValue": 0, - "maxValue": 256, - "writable": true - } - - ] - }, - { - "id": "05347200-416e-4b75-b4e3-6f913a2a7e76", - "name": "boblight", - "displayName": "Boblight", - "createMethods": ["auto"], - "interfaces": ["colorlight", "connectable"], - "paramTypes": [ - { - "id": "7b5b784d-d623-4a2e-b081-9be84b1ce1a8", - "name": "channel", - "displayName": "Channel", - "type": "int", - "defaultValue": -1 - } - ], - "stateTypes": [ - { - "id": "bb40f1bd-62b9-485e-86a1-b0c820a93b8a", - "name": "connected", - "displayName": "connected", - "defaultValue": false, - "displayNameEvent": "Connected changed", - "type": "bool" - }, - { - "id": "95aec7b5-247a-42a2-8748-273b034b988c", - "name": "power", - "displayName": "Power", - "defaultValue": false, - "type": "bool", - "displayNameEvent": "Power changed", - "displayNameAction": "Set power", - "writable": true - }, - { - "id": "0a92eab5-233c-4081-840b-15578091365c", - "name": "brightness", - "displayName": "Brightness", - "defaultValue": 100, - "type": "int", - "displayNameEvent": "Brightness changed", - "displayNameAction": "Set brightness", - "writable": true, - "minValue": 0, - "maxValue": 100 - }, - { - "id": "b6f24e6f-d2a8-4f22-b40f-3a0e38bdabe0", - "name": "colorTemperature", - "displayName": "Color Temperature", - "defaultValue": 0, - "type": "int", - "displayNameEvent": "Color Temperature changed", - "displayNameAction": "Set color temperature", - "writable": true, - "minValue": 0, - "maxValue": 100 - }, - { - "id": "a213d2d1-bd29-4a16-8459-520aa919ae67", - "name": "color", - "displayName": "Color", - "defaultValue": "#ffffff", - "type": "QColor", - "displayNameEvent": "Color changed", - "displayNameAction": "Set color", - "writable": true - } - ] - } - ] - } - ] -} diff --git a/boblight/meta.json b/boblight/meta.json deleted file mode 100644 index 1be06a36..00000000 --- a/boblight/meta.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "title": "Boblight", - "tagline": "Connect to LED strips driven by Boblight.", - "icon": "boblight.png", - "stability": "community", - "offline": true, - "technologies": [ - "network" - ], - "categories": [ - "light" - ] -} diff --git a/boblight/translations/d5271bea-1362-4cc6-888f-2ebe80bad46a-en_US.ts b/boblight/translations/d5271bea-1362-4cc6-888f-2ebe80bad46a-en_US.ts deleted file mode 100644 index 4276d182..00000000 --- a/boblight/translations/d5271bea-1362-4cc6-888f-2ebe80bad46a-en_US.ts +++ /dev/null @@ -1,154 +0,0 @@ - - - - - Boblight - - Boblight - The name of the ThingClass ({05347200-416e-4b75-b4e3-6f913a2a7e76}) ----------- -The name of the vendor ({f0c9dd91-c2b0-4cd0-b161-a17fee9d2303}) ----------- -The name of the plugin Boblight ({d5271bea-1362-4cc6-888f-2ebe80bad46a}) - - - - Boblight server - The name of the ThingClass ({f267a7f4-ed75-4026-9b97-98884d7f4399}) - - - - Host Address - The name of the ParamType (ThingClass: boblightServer, Type: thing, ID: {de82ea8c-2f1e-4b93-b85a-f6a0b7f87e4a}) - - - - Port - The name of the ParamType (ThingClass: boblightServer, Type: thing, ID: {8cbe5ef8-6b45-441e-9051-08d48f3948da}) - - - - Channels - The name of the ParamType (ThingClass: boblightServer, Type: thing, ID: {277f2458-d932-4a6e-a7bb-58814ab99663}) - - - - Connected changed - The name of the EventType ({bb40f1bd-62b9-485e-86a1-b0c820a93b8a}) of ThingClass boblight ----------- -The name of the EventType ({638fb9ec-4797-4ef6-a9b6-d935f1c49e17}) of ThingClass boblightServer - - - - connected - The name of the ParamType (ThingClass: boblight, EventType: connected, ID: {bb40f1bd-62b9-485e-86a1-b0c820a93b8a}) ----------- -The name of the StateType ({bb40f1bd-62b9-485e-86a1-b0c820a93b8a}) of ThingClass boblight ----------- -The name of the ParamType (ThingClass: boblightServer, EventType: connected, ID: {638fb9ec-4797-4ef6-a9b6-d935f1c49e17}) ----------- -The name of the StateType ({638fb9ec-4797-4ef6-a9b6-d935f1c49e17}) of ThingClass boblightServer - - - - Priority changed - The name of the EventType ({60d345e8-757c-4bc2-a96b-31121fc84356}) of ThingClass boblightServer - - - - Priority - The name of the ParamType (ThingClass: boblightServer, ActionType: priority, ID: {60d345e8-757c-4bc2-a96b-31121fc84356}) ----------- -The name of the ParamType (ThingClass: boblightServer, EventType: priority, ID: {60d345e8-757c-4bc2-a96b-31121fc84356}) ----------- -The name of the StateType ({60d345e8-757c-4bc2-a96b-31121fc84356}) of ThingClass boblightServer - - - - Set priority - The name of the ActionType ({60d345e8-757c-4bc2-a96b-31121fc84356}) of ThingClass boblightServer - - - - Channel - The name of the ParamType (ThingClass: boblight, Type: thing, ID: {7b5b784d-d623-4a2e-b081-9be84b1ce1a8}) - - - - Power changed - The name of the EventType ({95aec7b5-247a-42a2-8748-273b034b988c}) of ThingClass boblight - - - - Power - The name of the ParamType (ThingClass: boblight, ActionType: power, ID: {95aec7b5-247a-42a2-8748-273b034b988c}) ----------- -The name of the ParamType (ThingClass: boblight, EventType: power, ID: {95aec7b5-247a-42a2-8748-273b034b988c}) ----------- -The name of the StateType ({95aec7b5-247a-42a2-8748-273b034b988c}) of ThingClass boblight - - - - Set power - The name of the ActionType ({95aec7b5-247a-42a2-8748-273b034b988c}) of ThingClass boblight - - - - Brightness changed - The name of the EventType ({0a92eab5-233c-4081-840b-15578091365c}) of ThingClass boblight - - - - Brightness - The name of the ParamType (ThingClass: boblight, ActionType: brightness, ID: {0a92eab5-233c-4081-840b-15578091365c}) ----------- -The name of the ParamType (ThingClass: boblight, EventType: brightness, ID: {0a92eab5-233c-4081-840b-15578091365c}) ----------- -The name of the StateType ({0a92eab5-233c-4081-840b-15578091365c}) of ThingClass boblight - - - - Set brightness - The name of the ActionType ({0a92eab5-233c-4081-840b-15578091365c}) of ThingClass boblight - - - - Color Temperature changed - The name of the EventType ({b6f24e6f-d2a8-4f22-b40f-3a0e38bdabe0}) of ThingClass boblight - - - - Color Temperature - The name of the ParamType (ThingClass: boblight, ActionType: colorTemperature, ID: {b6f24e6f-d2a8-4f22-b40f-3a0e38bdabe0}) ----------- -The name of the ParamType (ThingClass: boblight, EventType: colorTemperature, ID: {b6f24e6f-d2a8-4f22-b40f-3a0e38bdabe0}) ----------- -The name of the StateType ({b6f24e6f-d2a8-4f22-b40f-3a0e38bdabe0}) of ThingClass boblight - - - - Set color temperature - The name of the ActionType ({b6f24e6f-d2a8-4f22-b40f-3a0e38bdabe0}) of ThingClass boblight - - - - Color changed - The name of the EventType ({a213d2d1-bd29-4a16-8459-520aa919ae67}) of ThingClass boblight - - - - Color - The name of the ParamType (ThingClass: boblight, ActionType: color, ID: {a213d2d1-bd29-4a16-8459-520aa919ae67}) ----------- -The name of the ParamType (ThingClass: boblight, EventType: color, ID: {a213d2d1-bd29-4a16-8459-520aa919ae67}) ----------- -The name of the StateType ({a213d2d1-bd29-4a16-8459-520aa919ae67}) of ThingClass boblight - - - - Set color - The name of the ActionType ({a213d2d1-bd29-4a16-8459-520aa919ae67}) of ThingClass boblight - - - - diff --git a/debian/control b/debian/control index 49ef4ffd..fb5d2c60 100644 --- a/debian/control +++ b/debian/control @@ -2,8 +2,7 @@ Source: nymea-plugins Section: utils Priority: optional Maintainer: Nymea GmbH -Build-depends: libboblight-dev, - debhelper (>= 0.0.0), +Build-depends: debhelper (>= 0.0.0), libnymea-dev (>= 0.26~), libnymea-mqtt-dev, libnymea-gpio-dev (>= 1.0.0~), @@ -80,17 +79,6 @@ Description: nymea integration plugin for bluos This package contains the nymea integration plugin for bluos based media devices -Package: nymea-plugin-boblight -Architecture: any -Depends: ${shlibs:Depends}, - ${misc:Depends}, -Conflicts: nymea-plugins-translations (< 1.0.1) -Description: nymea integration plugin for boblight - This package contains the nymea integration plugin for boblight. Boblight allows - controlling LEDs via home-brew controllers. See https://github.com/arvydas/boblight - for informations on boblight. - - Package: nymea-plugin-bose Architecture: any Depends: ${shlibs:Depends}, diff --git a/debian/nymea-plugin-boblight.install.in b/debian/nymea-plugin-boblight.install.in deleted file mode 100644 index 2966e0f1..00000000 --- a/debian/nymea-plugin-boblight.install.in +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/@DEB_HOST_MULTIARCH@/nymea/plugins/libnymea_integrationpluginboblight.so -boblight/translations/*qm usr/share/nymea/translations/ diff --git a/nymea-plugins.pro b/nymea-plugins.pro index 6e9da803..1988023e 100644 --- a/nymea-plugins.pro +++ b/nymea-plugins.pro @@ -7,7 +7,6 @@ PLUGIN_DIRS = \ awattar \ bimmerconnected \ bluos \ - boblight \ bose \ bosswerk \ coinmarketcap \