etm-powersync-plugins/boblight/devicepluginboblight.cpp
2020-01-23 12:48:25 +01:00

298 lines
12 KiB
C++

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* 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 <https://www.gnu.org/licenses/>.
*
* 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 "devicepluginboblight.h"
#include "devices/device.h"
#include "bobclient.h"
#include "plugininfo.h"
#include "plugintimer.h"
#include <QDebug>
#include <QStringList>
#include <QtMath>
DevicePluginBoblight::DevicePluginBoblight()
{
}
void DevicePluginBoblight::init()
{
m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(15);
connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginBoblight::guhTimer);
}
void DevicePluginBoblight::deviceRemoved(Device *device)
{
BobClient *client = m_bobClients.take(device->id());
if (device->deviceClassId() == boblightServerDeviceClassId) {
client->deleteLater();
}
}
void DevicePluginBoblight::startMonitoringAutoDevices()
{
m_canCreateAutoDevices = true;
qCDebug(dcBoblight()) << "Populating auto devices" << myDevices().count();
QHash<DeviceId, int> parentDevices;
QHash<DeviceId, Device*> deviceIds;
foreach (Device *device, myDevices()) {
deviceIds.insert(device->id(), device);
if (device->deviceClassId() == boblightServerDeviceClassId) {
// qWarning() << "Device" << device->id() << "is bridge";
if (!parentDevices.contains(device->id())) {
parentDevices[device->id()] = 0;
}
} else if (device->deviceClassId() == boblightDeviceClassId) {
// qWarning() << "Device" << device->id() << "is child to bridge" << device->parentId();
parentDevices[device->parentId()] += 1;
}
}
QList<DeviceDescriptor> descriptors;
foreach (const DeviceId &id, parentDevices.keys()) {
if (parentDevices.value(id) < deviceIds.value(id)->paramValue(boblightServerDeviceChannelsParamTypeId).toInt()) {
for (int i = parentDevices.value(id); i < deviceIds.value(id)->paramValue(boblightServerDeviceChannelsParamTypeId).toInt(); i++) {
DeviceDescriptor descriptor(boblightDeviceClassId, deviceIds.value(id)->name() + " " + QString::number(i + 1), QString(), id);
descriptor.setParams(ParamList() << Param(boblightDeviceChannelParamTypeId, i));
qCDebug(dcBoblight()) << "Adding new boblight channel" << i + 1;
descriptors.append(descriptor);
}
}
}
if (!descriptors.isEmpty()) {
emit autoDevicesAppeared(descriptors);
}
}
void DevicePluginBoblight::guhTimer()
{
foreach (BobClient *client, m_bobClients) {
if (!client->connected()) {
client->connectToBoblight();
}
}
}
void DevicePluginBoblight::onPowerChanged(int channel, bool power)
{
qCDebug(dcBoblight()) << "power changed" << channel << power;
BobClient *sndr = dynamic_cast<BobClient*>(sender());
foreach (Device* device, myDevices()) {
if (m_bobClients.value(device->parentId()) == sndr && device->paramValue(boblightDeviceChannelParamTypeId).toInt() == channel) {
qCDebug(dcBoblight()) << "setting state power" << power;
device->setStateValue(boblightPowerStateTypeId, power);
}
}
}
void DevicePluginBoblight::onBrightnessChanged(int channel, int brightness)
{
BobClient *sndr = dynamic_cast<BobClient*>(sender());
foreach (Device* device, myDevices()) {
if (m_bobClients.value(device->parentId()) == sndr && device->paramValue(boblightDeviceChannelParamTypeId).toInt() == channel) {
device->setStateValue(boblightBrightnessStateTypeId, brightness);
}
}
}
void DevicePluginBoblight::onColorChanged(int channel, const QColor &color)
{
BobClient *sndr = dynamic_cast<BobClient*>(sender());
foreach (Device* device, myDevices()) {
if (m_bobClients.value(device->parentId()) == sndr && device->paramValue(boblightDeviceChannelParamTypeId).toInt() == channel) {
device->setStateValue(boblightColorStateTypeId, color);
}
}
}
void DevicePluginBoblight::onPriorityChanged(int priority)
{
BobClient *sndr = dynamic_cast<BobClient*>(sender());
foreach (Device* device, myDevices()) {
if (device->deviceClassId() == boblightServerDeviceClassId && m_bobClients.value(device->id()) == sndr) {
device->setStateValue(boblightServerPriorityStateTypeId, priority);
}
}
}
QColor DevicePluginBoblight::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 DevicePluginBoblight::setupDevice(DeviceSetupInfo *info)
{
Device *device = info->device();
if (device->deviceClassId() == boblightServerDeviceClassId) {
BobClient *bobClient = new BobClient(device->paramValue(boblightServerDeviceHostAddressParamTypeId).toString(), device->paramValue(boblightServerDevicePortParamTypeId).toInt(), this);
bool connected = bobClient->connectToBoblight();
if (!connected) {
qCWarning(dcBoblight()) << "Error connecting to boblight on" << device->paramValue(boblightServerDeviceHostAddressParamTypeId).toString();
} else {
qCDebug(dcBoblight()) << "Connected to boblight";
}
bobClient->setPriority(device->stateValue(boblightServerPriorityStateTypeId).toInt());
device->setStateValue(boblightServerConnectedStateTypeId, connected);
m_bobClients.insert(device->id(), bobClient);
connect(bobClient, &BobClient::connectionChanged, this, &DevicePluginBoblight::onConnectionChanged);
connect(bobClient, &BobClient::powerChanged, this, &DevicePluginBoblight::onPowerChanged);
connect(bobClient, &BobClient::brightnessChanged, this, &DevicePluginBoblight::onBrightnessChanged);
connect(bobClient, &BobClient::colorChanged, this, &DevicePluginBoblight::onColorChanged);
connect(bobClient, &BobClient::priorityChanged, this, &DevicePluginBoblight::onPriorityChanged);
} else if (device->deviceClassId() == boblightDeviceClassId) {
BobClient *bobClient = m_bobClients.value(device->parentId());
device->setStateValue(boblightConnectedStateTypeId, bobClient->connected());
m_bobClients.insert(device->id(), bobClient);
}
info->finish(Device::DeviceErrorNoError);
}
void DevicePluginBoblight::postSetupDevice(Device *device)
{
if (device->deviceClassId() == boblightServerDeviceClassId && m_canCreateAutoDevices) {
startMonitoringAutoDevices();
}
if (device->deviceClassId() == boblightDeviceClassId) {
BobClient *bobClient = m_bobClients.value(device->parentId());
if (bobClient && bobClient->connected()) {
device->setStateValue(boblightConnectedStateTypeId, bobClient->connected());
QColor color = device->stateValue(boblightColorStateTypeId).value<QColor>();
int brightness = device->stateValue(boblightBrightnessStateTypeId).toInt();
bool power = device->stateValue(boblightPowerStateTypeId).toBool();
bobClient->setColor(device->paramValue(boblightDeviceChannelParamTypeId).toInt(), color);
bobClient->setBrightness(device->paramValue(boblightDeviceChannelParamTypeId).toInt(), brightness);
bobClient->setPower(device->paramValue(boblightDeviceChannelParamTypeId).toInt(), power);
}
}
}
void DevicePluginBoblight::executeAction(DeviceActionInfo *info)
{
Device *device = info->device();
Action action = info->action();
qCDebug(dcBoblight()) << "Execute action for boblight" << action.params();
if (device->deviceClassId() == boblightServerDeviceClassId) {
BobClient *bobClient = m_bobClients.value(device->id());
if (!bobClient || !bobClient->connected()) {
qCWarning(dcBoblight()) << "Boblight on" << device->paramValue(boblightServerDeviceHostAddressParamTypeId).toString() << "not connected";
info->finish(Device::DeviceErrorHardwareNotAvailable);
return;
}
if (action.actionTypeId() == boblightServerPriorityActionTypeId) {
bobClient->setPriority(action.param(boblightServerPriorityActionPriorityParamTypeId).value().toInt());
info->finish(Device::DeviceErrorNoError);
return;
}
qCWarning(dcBoblight()) << "Unhandled action" << action.actionTypeId() << "for BoblightServer device" << info;
info->finish(Device::DeviceErrorActionTypeNotFound);
return;
}
if (device->deviceClassId() == boblightDeviceClassId) {
BobClient *bobClient = m_bobClients.value(device->parentId());
if (!bobClient || !bobClient->connected()) {
qCWarning(dcBoblight()) << "Boblight not connected";
info->finish(Device::DeviceErrorHardwareNotAvailable);
return;
}
if (action.actionTypeId() == boblightPowerActionTypeId) {
bobClient->setPower(device->paramValue(boblightDeviceChannelParamTypeId).toInt(), action.param(boblightPowerActionPowerParamTypeId).value().toBool());
info->finish(Device::DeviceErrorNoError);
return;
}
if (action.actionTypeId() == boblightColorActionTypeId) {
bobClient->setColor(device->paramValue(boblightDeviceChannelParamTypeId).toInt(), action.param(boblightColorActionColorParamTypeId).value().value<QColor>());
info->finish(Device::DeviceErrorNoError);
return;
}
if (action.actionTypeId() == boblightBrightnessActionTypeId) {
bobClient->setBrightness(device->paramValue(boblightDeviceChannelParamTypeId).toInt(), action.param(boblightBrightnessActionBrightnessParamTypeId).value().toInt());
info->finish(Device::DeviceErrorNoError);
return;
}
if (action.actionTypeId() == boblightColorTemperatureActionTypeId) {
bobClient->setColor(device->paramValue(boblightDeviceChannelParamTypeId).toInt(), tempToRgb(action.param(boblightColorTemperatureActionColorTemperatureParamTypeId).value().toInt()));
info->finish(Device::DeviceErrorNoError);
return;
}
info->finish(Device::DeviceErrorActionTypeNotFound);
return;
}
info->finish(Device::DeviceErrorDeviceClassNotFound);
}
void DevicePluginBoblight::onConnectionChanged()
{
BobClient *bobClient = static_cast<BobClient *>(sender());
qCDebug(dcBoblight()) << "Connection changed. BobClient:" << bobClient << bobClient->connected() << m_bobClients.keys(bobClient);
foreach (const DeviceId &deviceId, m_bobClients.keys(bobClient)) {
foreach (Device *device, myDevices()) {
if (device->id() == deviceId || device->parentId() == deviceId) {
device->setStateValue(boblightConnectedStateTypeId, bobClient->connected());
break;
}
}
}
}