From 7dd778628db22d745828401d9e3aeaec63c3c089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Fri, 16 Mar 2018 19:21:07 +0100 Subject: [PATCH] Fix avea plugin --- elgato/aveabulb.cpp | 271 +++++++++++++++++++++++++++++---- elgato/aveabulb.h | 39 ++++- elgato/aveacolor.cpp | 59 ++++++- elgato/aveacolor.h | 31 +++- elgato/devicepluginelgato.cpp | 101 ++++++++++-- elgato/devicepluginelgato.h | 11 +- elgato/devicepluginelgato.json | 109 +++++++++++-- elgato/elgato.pro | 2 - 8 files changed, 554 insertions(+), 69 deletions(-) diff --git a/elgato/aveabulb.cpp b/elgato/aveabulb.cpp index bcb5e411..0dc10f64 100644 --- a/elgato/aveabulb.cpp +++ b/elgato/aveabulb.cpp @@ -1,4 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * * * * This file is part of nymea. * * * @@ -19,8 +21,11 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "aveabulb.h" +#include "aveacolor.h" #include "extern-plugininfo.h" +#include + AveaBulb::AveaBulb(Device *device, BluetoothLowEnergyDevice *bluetoothDevice, QObject *parent) : QObject(parent), m_device(device), @@ -40,6 +45,50 @@ BluetoothLowEnergyDevice *AveaBulb::bluetoothDevice() return m_bluetoothDevice; } +bool AveaBulb::setPower(bool power) +{ + if (!m_bluetoothDevice->connected()) + return false; + + if (!m_colorService) + return false; + + qCDebug(dcElgato()) << "Set power" << (power ? "on" : "off"); + + // Sync current color + if (power) + return syncColor(); + + // Power off + QByteArray command; + QDataStream stream(&command, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + + quint8 commandId = static_cast(ColorMessageColor); + quint16 fade = static_cast(m_fade); + quint16 constant = 0x000a; + quint16 white = 0 | 0x8000; + quint16 red = 0 | 0x3000; + quint16 green = 0 | 0x2000; + quint16 blue = 0 | 0x1000; + + stream << commandId << fade << constant << white << red << green << blue; + + qCDebug(dcElgato()) << "Set color data -->" << command.toHex(); + + m_colorService->writeCharacteristic(m_colorCharacteristic, command); + return true; + +} + +bool AveaBulb::setBulbName(const QString &name) +{ + m_bulbName = name; + + // TODO: + return true; +} + bool AveaBulb::setColor(const QColor &color) { if (!m_bluetoothDevice->connected()) @@ -48,12 +97,138 @@ bool AveaBulb::setColor(const QColor &color) if (!m_colorService) return false; + qCDebug(dcElgato()) << "-->" << color.toRgb(); + // Convert rgb to wrgb QByteArray command; - command.append(QByteArray::fromHex("35")); + QDataStream stream(&command, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); - qCDebug(dcElgato()) << color << command; + m_red = scaleColorValueUp(color.red()); + m_green = scaleColorValueUp(color.green()); + m_blue = scaleColorValueUp(color.blue()); + m_color = color; + + return syncColor(); +} + +bool AveaBulb::setBrightness(int percentage) +{ + if (!m_bluetoothDevice->connected()) + return false; + + if (!m_colorService) + return false; + + quint16 brightnessValue = qRound(4095.0 * percentage / 100.0); + qCDebug(dcElgato()) << "Brightness value" << percentage << "% -->" << brightnessValue; + + QByteArray command; + QDataStream stream(&command, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + stream << static_cast(ColorMessageBrightness); + stream << brightnessValue; + + m_colorService->writeCharacteristic(m_colorCharacteristic, command); + return true; +} + +bool AveaBulb::setFade(int fade) +{ + m_fade = fade; + return syncColor(); +} + +bool AveaBulb::setWhite(int white) +{ + m_white = white; + return syncColor(); +} + +bool AveaBulb::setRed(int red) +{ + m_red = red; + return syncColor(); +} + +bool AveaBulb::setGreen(int green) +{ + m_green = green; + return syncColor(); +} + +bool AveaBulb::setBlue(int blue) +{ + m_blue = blue; + return syncColor(); +} + +bool AveaBulb::loadValues() +{ + if (!m_bluetoothDevice->connected()) + return false; + + if (!m_colorService) + return false; + + // Request color + m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex("35")); + + // Request brightness + m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex("57")); + + // Request name + m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex("58")); + return true; +} + +quint16 AveaBulb::scaleColorValueUp(int colorValue) +{ + return static_cast(qRound(4095.0 * colorValue / 255.0)); +} + +int AveaBulb::scaleColorValueDown(quint16 colorValue) +{ + return qRound(255.0 * colorValue / 4095.0); +} + +bool AveaBulb::syncColor() +{ + if (!m_bluetoothDevice->connected()) + return false; + + if (!m_colorService) + return false; + + if (!m_device->stateValue(aveaPowerStateTypeId).toBool()) { + qCWarning(dcElgato()) << "Not syncing color because power off"; + return false; + } + + m_device->setStateValue(aveaBlueStateTypeId, m_white); + m_device->setStateValue(aveaRedStateTypeId, m_red); + m_device->setStateValue(aveaGreenStateTypeId, m_green); + m_device->setStateValue(aveaBlueStateTypeId, m_blue); + m_device->setStateValue(aveaColorStateTypeId, QColor(scaleColorValueDown(m_red), scaleColorValueDown(m_green), scaleColorValueDown(m_blue))); + + // Convert rgb to wrgb + QByteArray command; + QDataStream stream(&command, QIODevice::WriteOnly); + stream.setByteOrder(QDataStream::LittleEndian); + + quint8 commandId = static_cast(ColorMessageColor); + quint16 fade = static_cast(m_fade); + quint16 constant = 0x000a; + quint16 white = m_white | 0x8000; + quint16 red = m_red | 0x3000; + quint16 green = m_green | 0x2000; + quint16 blue = m_blue | 0x1000; + + stream << commandId << fade << constant << white << red << green << blue; + + qCDebug(dcElgato()) << "----> Sync" << command.toHex(); + m_colorService->writeCharacteristic(m_colorCharacteristic, command); return true; } @@ -70,7 +245,6 @@ void AveaBulb::onConnectedChanged(const bool &connected) m_colorService = nullptr; m_imageService = nullptr; } - } void AveaBulb::onServiceDiscoveryFinished() @@ -119,7 +293,7 @@ void AveaBulb::onColorServiceStateChanged(const QLowEnergyService::ServiceState } // Data characteristic - m_colorCharacteristic = m_colorService->characteristic(QBluetoothUuid(QUuid("f815e811-456c-6761-746f-4d756e696368"))); + m_colorCharacteristic = m_colorService->characteristic(colorCharacteristicUuid); if (!m_colorCharacteristic.isValid()) { qCWarning(dcElgato()) << "Invalid color data characteristic."; } @@ -128,37 +302,72 @@ void AveaBulb::onColorServiceStateChanged(const QLowEnergyService::ServiceState QLowEnergyDescriptor notificationDescriptor = m_colorCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration); m_colorService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100")); - // Get current configuration - - // Color - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex("35")); - - // Brightness - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex("57")); - - // Name - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex("58")); - + // Load current configuration + loadValues(); } void AveaBulb::onColorServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value) { - qCDebug(dcElgato()) << "Color characteristic changed" << characteristic.uuid().toString() << value; - - if (value.startsWith(QByteArray::fromHex("35"))) { - qCDebug(dcElgato()) << "Received color notification"; - qCDebug(dcElgato()) << " Fade" << value.mid(1, 2); - qCDebug(dcElgato()) << " Fixed value" << value.mid(3, 2); - qCDebug(dcElgato()) << " White" << value.mid(5, 2); - qCDebug(dcElgato()) << " Red" << value.mid(7, 2); - qCDebug(dcElgato()) << " Green" << value.mid(9, 2); - qCDebug(dcElgato()) << " Blue" << value.mid(11, 2); - } else if (value.startsWith(QByteArray::fromHex("57"))) { - qCDebug(dcElgato()) << "Received brightness notification"; - qCDebug(dcElgato()) << " Fade" << value.mid(1, 2); - } else if (value.startsWith(QByteArray::fromHex("58"))) { - qCDebug(dcElgato()) << "Received name notification"; - qCDebug(dcElgato()) << " Name" << value.mid(1, value.count() - 2); + if (characteristic.uuid() != colorCharacteristicUuid) { + qCWarning(dcElgato()) << "Unhandled color service characteristic notification received" << value.toHex(); + return; } + + //qCDebug(dcElgato()) << "Color characteristic changed" << characteristic.uuid().toString() << value.toHex(); + + QByteArray payload = value; + QDataStream stream(&payload, QIODevice::ReadOnly); + quint8 messageType; + stream.setByteOrder(QDataStream::LittleEndian); + stream >> messageType; + + //qCDebug(dcElgato()) << "Message type" << messageType << static_cast(messageType); + + switch (messageType) { + case ColorMessageColor: { + quint16 whiteCurrentValue = 0; quint16 blueCurrentValue = 0; quint16 greenCurrentValue = 0; quint16 redCurrentValue = 0; + quint16 whiteTargetValue = 0; quint16 blueTargetValue = 0; quint16 greenTargetValue = 0; quint16 redTargetValue = 0; + + // Read current color + stream >> whiteCurrentValue >> blueCurrentValue >> greenCurrentValue >> redCurrentValue; + + // Read target color + stream >> whiteTargetValue >> blueTargetValue >> greenTargetValue >> redTargetValue; + + // Convert color values + quint16 whiteCurrentAdjustedValue = whiteCurrentValue; + quint16 blueCurrentAdjustedValue = blueCurrentValue ^ 0x1000; + quint16 greenCurrentAdjustedValue = greenCurrentValue ^ 0x2000; + quint16 redCurrentAdjustedValue = redCurrentValue ^ 0x3000; + + qCDebug(dcElgato()) << "Received color notification:"; + qCDebug(dcElgato()) << " white (current):" << value.mid(1, 2).toHex() << whiteCurrentValue << whiteCurrentAdjustedValue; + qCDebug(dcElgato()) << " blue (current):" << value.mid(3, 2).toHex() << blueCurrentValue << blueCurrentAdjustedValue; + qCDebug(dcElgato()) << " green (current):" << value.mid(5, 2).toHex() << greenCurrentValue << greenCurrentAdjustedValue; + qCDebug(dcElgato()) << " red (current):" << value.mid(7, 2).toHex() << redCurrentValue << redCurrentAdjustedValue; + qCDebug(dcElgato()) << " white (target) :" << value.mid(9, 2).toHex() << whiteTargetValue; + qCDebug(dcElgato()) << " blue (target) :" << value.mid(11, 2).toHex() << blueTargetValue; + qCDebug(dcElgato()) << " green (target) :" << value.mid(13, 2).toHex() << greenTargetValue; + qCDebug(dcElgato()) << " red (target) :" << value.mid(15, 2).toHex() << redTargetValue; + + break; + } + case ColorMessageBrightness: { + quint16 brightnessValue = 0; + stream >> brightnessValue; + int brightnessPercentage = qRound(brightnessValue * 100 / 4095.0); + qCDebug(dcElgato()) << "Brightness notification" << value.mid(1, 2).toHex() << brightnessValue << "-->" << brightnessPercentage << "%"; + m_device->setStateValue(aveaBrightnessStateTypeId, brightnessPercentage); + break; + } + case ColorMessageName: { + qCDebug(dcElgato()) << "Name notification:" << value.mid(1, value.count() - 2); + break; + } + default: + qCWarning(dcElgato()) << "Unhandled color characteristic notification received" << value.toHex(); + break; + } + } diff --git a/elgato/aveabulb.h b/elgato/aveabulb.h index 08e362eb..5cc31072 100644 --- a/elgato/aveabulb.h +++ b/elgato/aveabulb.h @@ -1,4 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * * * * This file is part of nymea. * * * @@ -30,22 +32,55 @@ #include "hardware/bluetoothlowenergy/bluetoothlowenergydevice.h" static QBluetoothUuid colorServiceUuid = QBluetoothUuid(QUuid("f815e810-456c-6761-746f-4d756e696368")); +static QBluetoothUuid colorCharacteristicUuid = QBluetoothUuid(QUuid("f815e811-456c-6761-746f-4d756e696368")); + static QBluetoothUuid imageServiceUuid = QBluetoothUuid(QUuid("f815e500-456c-6761-746f-4d756e696368")); class AveaBulb : public QObject { Q_OBJECT public: + enum ColorMessage { + ColorMessageColor = 0x35, + ColorMessageBrightness = 0x57, + ColorMessageName = 0x58 + }; + Q_ENUM(ColorMessage) + explicit AveaBulb(Device *device, BluetoothLowEnergyDevice *bluetoothDevice, QObject *parent = nullptr); Device *device(); BluetoothLowEnergyDevice *bluetoothDevice(); + bool setPower(bool power); + bool setBulbName(const QString &name); bool setColor(const QColor &color); + bool setBrightness(int percentage); + bool setFade(int fade); + + bool setWhite(int white); + bool setRed(int red); + bool setGreen(int green); + bool setBlue(int blue); + + bool loadValues(); + bool syncColor(); private: - Device *m_device; - BluetoothLowEnergyDevice *m_bluetoothDevice; + Device *m_device = nullptr; + BluetoothLowEnergyDevice *m_bluetoothDevice = nullptr; + + QString m_bulbName; + QColor m_color; + int m_brightness = 0; + int m_fade = 0; + int m_white = 0; + int m_red = 0; + int m_green = 0; + int m_blue = 0; + + quint16 scaleColorValueUp(int colorValue); + int scaleColorValueDown(quint16 colorValue); private: QLowEnergyService *m_colorService = nullptr; diff --git a/elgato/aveacolor.cpp b/elgato/aveacolor.cpp index df3da5b4..dd4b6f9e 100644 --- a/elgato/aveacolor.cpp +++ b/elgato/aveacolor.cpp @@ -1,12 +1,57 @@ -#include "aveacolor.h" +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of nymea. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -AveaColor::AveaColor(const QColor &color) +#include "extern-plugininfo.h" + +AveaColor::AveaColor(const QColor &color): + m_color(color) { // Convert rgb to wrgb - ColorRgbw rgbw = rgbToRgbw(color.red(), color.green(), color.blue()); - Q_UNUSED(rgbw) + qCDebug(dcElgato()) << "Convert color" << m_color.red() << m_color.green() << m_color.blue(); + ColorRgbw rgbw = rgbToRgbw(m_color.red(), m_color.green(), m_color.blue()); + m_white = rgbw.white; + m_red = rgbw.red; + m_green = rgbw.green; + m_blue = rgbw.blue; +} + +AveaColor::AveaColor(uint white, uint red, uint green, uint blue): + m_white(white), + m_red(red), + m_green(green), + m_blue(blue) +{ + // Convert rgbw to rgb + + // TODO + + +} + +QColor AveaColor::color() const +{ + return m_color; } uint AveaColor::white() const @@ -68,3 +113,9 @@ ColorRgbw AveaColor::rgbToRgbw(uint red, uint green, uint blue) rgbw.white = getWhite(rgbw); return rgbw; } + +QDebug operator<<(QDebug dbg, const AveaColor &color) +{ + dbg.nospace() << "AveaColor(" << color.color() << " | R:" << color.red() << " G:" << color.green() << "B:" << color.blue() << "W:" << color.white() << ")"; + return dbg; +} diff --git a/elgato/aveacolor.h b/elgato/aveacolor.h index a38041b1..352e4b29 100644 --- a/elgato/aveacolor.h +++ b/elgato/aveacolor.h @@ -1,8 +1,31 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * + * * + * This file is part of nymea. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library 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 library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #ifndef AVEACOLOR_H #define AVEACOLOR_H #include #include +#include struct ColorRgbw { uint red; @@ -11,11 +34,13 @@ struct ColorRgbw { uint white; }; - class AveaColor { public: AveaColor(const QColor &color); + AveaColor(uint white, uint red, uint green, uint blue); + + QColor color() const; uint white() const; uint red() const; @@ -25,6 +50,7 @@ public: QByteArray toByteArray(); private: + QColor m_color; uint m_white = 0; uint m_red = 0; uint m_green = 0; @@ -36,4 +62,7 @@ private: ColorRgbw rgbToRgbw(unsigned int red, unsigned int green, unsigned int blue); }; +QDebug operator<<(QDebug dbg, const AveaColor &color); + + #endif // AVEACOLOR_H diff --git a/elgato/devicepluginelgato.cpp b/elgato/devicepluginelgato.cpp index 22cb4f93..66ff680f 100644 --- a/elgato/devicepluginelgato.cpp +++ b/elgato/devicepluginelgato.cpp @@ -1,4 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * * * * This file is part of nymea. * * * @@ -408,6 +410,17 @@ DevicePluginElgato::DevicePluginElgato() } +DevicePluginElgato::~DevicePluginElgato() +{ + hardwareManager()->pluginTimerManager()->unregisterTimer(m_pluginTimer); +} + +void DevicePluginElgato::init() +{ + m_pluginTimer = hardwareManager()->pluginTimerManager()->registerTimer(10); + connect(m_pluginTimer, &PluginTimer::timeout, this, &DevicePluginElgato::onPluginTimer); +} + DeviceManager::DeviceError DevicePluginElgato::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) { Q_UNUSED(params) @@ -438,31 +451,86 @@ DeviceManager::DeviceSetupStatus DevicePluginElgato::setupDevice(Device *device) BluetoothLowEnergyDevice *bluetoothDevice = hardwareManager()->bluetoothLowEnergyManager()->registerDevice(deviceInfo, QLowEnergyController::PublicAddress); AveaBulb *bulb = new AveaBulb(device, bluetoothDevice, this); - m_bulbs.insert(device, bulb); - bulb->bluetoothDevice()->connectDevice(); return DeviceManager::DeviceSetupStatusSuccess; } return DeviceManager::DeviceSetupStatusFailure; } +void DevicePluginElgato::postSetupDevice(Device *device) +{ + AveaBulb *bulb = m_bulbs.value(device); + // Init values for restore + bulb->setBrightness(device->stateValue(aveaBrightnessStateTypeId).toInt()); + bulb->setFade(device->stateValue(aveaFadeStateTypeId).toInt()); + bulb->setWhite(device->stateValue(aveaWhiteStateTypeId).toInt()); + bulb->setRed(device->stateValue(aveaRedStateTypeId).toInt()); + bulb->setGreen(device->stateValue(aveaGreenStateTypeId).toInt()); + bulb->setBlue(device->stateValue(aveaBlueStateTypeId).toInt()); + + bulb->bluetoothDevice()->connectDevice(); +} + DeviceManager::DeviceError DevicePluginElgato::executeAction(Device *device, const Action &action) { - Q_UNUSED(action) - // check deviceClassId if (device->deviceClassId() == aveaDeviceClassId) { AveaBulb *bulb = m_bulbs.value(device); - Q_UNUSED(bulb) -// // check actionTypeId -// if (action.actionTypeId() == powerOffActionTypeId) { -// bulb->actionPowerOff(action.id()); -// return DeviceManager::DeviceErrorAsync; -// } else if (action.actionTypeId() == colorActionTypeId) { + if (action.actionTypeId() == aveaPowerActionTypeId) { + bool power = action.param(aveaPowerStateParamTypeId).value().toBool(); + device->setStateValue(aveaPowerStateTypeId, power); + if (!bulb->setPower(power)) + return DeviceManager::DeviceErrorHardwareNotAvailable; -// return DeviceManager::DeviceErrorNoError; -// } + return DeviceManager::DeviceErrorNoError; + } else if (action.actionTypeId() == aveaBrightnessActionTypeId) { + int percentage = action.param(aveaBrightnessStateParamTypeId).value().toInt(); + if (!bulb->setBrightness(percentage)) + return DeviceManager::DeviceErrorHardwareNotAvailable; + + device->setStateValue(aveaBrightnessStateTypeId, percentage); + return DeviceManager::DeviceErrorNoError; + } else if (action.actionTypeId() == aveaColorActionTypeId) { + QColor color = action.param(aveaColorStateParamTypeId).value().value(); + if (!bulb->setColor(color)) + return DeviceManager::DeviceErrorHardwareNotAvailable; + + device->setStateValue(aveaColorStateTypeId, color); + return DeviceManager::DeviceErrorNoError; + } else if (action.actionTypeId() == aveaWhiteActionTypeId) { + int whiteValue = action.param(aveaWhiteStateParamTypeId).value().toInt(); + if (!bulb->setWhite(whiteValue)) + return DeviceManager::DeviceErrorHardwareNotAvailable; + + device->setStateValue(aveaWhiteStateTypeId, whiteValue); + return DeviceManager::DeviceErrorNoError; + } else if (action.actionTypeId() == aveaGreenActionTypeId) { + int greenValue = action.param(aveaGreenStateParamTypeId).value().toInt(); + if (!bulb->setGreen(greenValue)) + return DeviceManager::DeviceErrorHardwareNotAvailable; + + return DeviceManager::DeviceErrorNoError; + } else if (action.actionTypeId() == aveaRedActionTypeId) { + int redValue = action.param(aveaRedStateParamTypeId).value().toInt(); + if (!bulb->setRed(redValue)) + return DeviceManager::DeviceErrorHardwareNotAvailable; + + return DeviceManager::DeviceErrorNoError; + } else if (action.actionTypeId() == aveaBlueActionTypeId) { + int blueValue = action.param(aveaBlueStateParamTypeId).value().toInt(); + if (!bulb->setBlue(blueValue)) + return DeviceManager::DeviceErrorHardwareNotAvailable; + + return DeviceManager::DeviceErrorNoError; + } else if (action.actionTypeId() == aveaFadeActionTypeId) { + int fadeValue = action.param(aveaFadeStateParamTypeId).value().toInt(); + device->setStateValue(aveaFadeStateTypeId, fadeValue); + if (!bulb->setFade(fadeValue)) + return DeviceManager::DeviceErrorHardwareNotAvailable; + + return DeviceManager::DeviceErrorNoError; + } return DeviceManager::DeviceErrorActionTypeNotFound; } @@ -490,6 +558,15 @@ bool DevicePluginElgato::verifyExistingDevices(const QBluetoothDeviceInfo &devic return false; } +void DevicePluginElgato::onPluginTimer() +{ + foreach (AveaBulb *bulb, m_bulbs.values()) { + if (!bulb->bluetoothDevice()->connected()) { + bulb->bluetoothDevice()->connectDevice(); + } + } +} + void DevicePluginElgato::onBluetoothDiscoveryFinished() { BluetoothDiscoveryReply *reply = static_cast(sender()); diff --git a/elgato/devicepluginelgato.h b/elgato/devicepluginelgato.h index 8144c7e3..65f79dbd 100644 --- a/elgato/devicepluginelgato.h +++ b/elgato/devicepluginelgato.h @@ -1,4 +1,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2016-2018 Simon Stürz * * * * This file is part of nymea. * * * @@ -21,9 +23,10 @@ #ifndef DEVICEPLUGINELGATO_H #define DEVICEPLUGINELGATO_H +#include "aveabulb.h" +#include "plugintimer.h" #include "plugin/deviceplugin.h" #include "hardware/bluetoothlowenergy/bluetoothlowenergydevice.h" -#include "aveabulb.h" class DevicePluginElgato : public DevicePlugin { @@ -34,17 +37,23 @@ class DevicePluginElgato : public DevicePlugin public: explicit DevicePluginElgato(); + ~DevicePluginElgato(); + void init() override; DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; + void postSetupDevice(Device *device) override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; void deviceRemoved(Device *device) override; private: + PluginTimer *m_pluginTimer = nullptr; QHash m_bulbs; + bool verifyExistingDevices(const QBluetoothDeviceInfo &deviceInfo); private slots: + void onPluginTimer(); void onBluetoothDiscoveryFinished(); }; diff --git a/elgato/devicepluginelgato.json b/elgato/devicepluginelgato.json index cfc40484..8626a936 100644 --- a/elgato/devicepluginelgato.json +++ b/elgato/devicepluginelgato.json @@ -1,37 +1,33 @@ { - "displayName": "Elgato", "id": "c5c03ad4-bfdb-444a-8eca-2c234c46cc27", "name": "Elgato", + "displayName": "Elgato", "vendors": [ { - "displayName": "Elgato", - "name": "elgato", "id": "90a3091d-1053-4f77-8dc3-92e27bbcebe7", + "name": "elgato", + "displayName": "Elgato", "deviceClasses": [ { "id": "164f9602-90ee-4693-bda3-9cafae37603e", "name": "avea", "displayName": "Avea", "deviceIcon": "LightBulb", - "criticalStateTypeId": "6d5e792a-c786-40d2-ae35-a48ac6fafcbc", - "basicTags": [ - "Device", - "Actuator", - "Lighting" - ], + "basicTags": ["Device", "Actuator", "Lighting"], + "interfaces": ["connectable"], "createMethods": ["discovery"], "paramTypes": [ { "id": "d7a5d96f-33dc-4dc3-a171-b1e89a5e1a4b", "name": "name", - "displayName": "name", + "displayName": "Name", "type": "QString", "inputType": "TextLine" }, { "id": "20932e39-00fd-40e3-8f39-850ba149844e", "name": "macAddress", - "displayName": "mac address", + "displayName": "MAC address", "type": "QString", "inputType": "MacAddress" } @@ -40,16 +36,27 @@ { "id": "6d5e792a-c786-40d2-ae35-a48ac6fafcbc", "name": "connected", - "displayName": "connected", - "displayNameEvent": "connected changed", + "displayName": "Connected", + "displayNameEvent": "Connected changed", "type": "bool", + "cached": false, + "defaultValue": false + }, + { + "id": "2b779968-ff4f-4a05-a466-074e14288a8c", + "name": "power", + "displayName": "Power", + "displayNameEvent": "Power changed", + "displayNameAction": "Set power", + "type": "bool", + "writable": true, "defaultValue": false }, { "id": "c38181a0-e19b-423f-8b66-dedda94e89b5", "name": "brightness", "displayName": "Brightness", - "displayNameEvent": "brightness changed", + "displayNameEvent": "Brightness changed", "displayNameAction": "Set brightness", "type": "int", "defaultValue": 100, @@ -62,14 +69,84 @@ { "id": "3f15637a-8272-4714-bd08-04806e05bbef", "name": "color", - "displayName": "color", - "displayNameEvent": "color changed", + "displayName": "Color", + "displayNameEvent": "Color changed", "displayNameAction": "Set color", "type": "QColor", "ruleRelevant": false, "eventRuleRelevant": false, "defaultValue": "#000000", "writable": true + }, + { + "id": "50f6a224-fb8d-487d-8774-1a0536e5b1aa", + "name": "white", + "displayName": "white", + "displayNameEvent": "white changed", + "displayNameAction": "Set white", + "type": "int", + "defaultValue": 0, + "ruleRelevant": false, + "minValue": 0, + "maxValue": 4095, + "eventRuleRelevant": false, + "writable": true + }, + { + "id": "50ab71d1-8970-4531-b1ad-f387d01bab90", + "name": "red", + "displayName": "Red", + "displayNameEvent": "Red changed", + "displayNameAction": "Set red", + "type": "int", + "defaultValue": 0, + "ruleRelevant": false, + "minValue": 0, + "maxValue": 4095, + "eventRuleRelevant": false, + "writable": true + }, + { + "id": "9e8ddebc-33fe-418a-895f-d8148fabcfee", + "name": "green", + "displayName": "Green", + "displayNameEvent": "Green changed", + "displayNameAction": "Set green", + "type": "int", + "defaultValue": 0, + "ruleRelevant": false, + "minValue": 0, + "maxValue": 4095, + "eventRuleRelevant": false, + "writable": true + }, + { + "id": "f4310747-d468-4d2e-abe4-b5e4d0245dad", + "name": "blue", + "displayName": "Blue", + "displayNameEvent": "Blue changed", + "displayNameAction": "Set blue", + "type": "int", + "defaultValue": 0, + "ruleRelevant": false, + "minValue": 0, + "maxValue": 4095, + "eventRuleRelevant": false, + "writable": true + }, + { + "id": "01ccda48-44c6-495b-b0a7-c2a0bf5a570d", + "name": "fade", + "displayName": "Fade", + "displayNameEvent": "Fade changed", + "displayNameAction": "Set fade", + "type": "int", + "defaultValue": 0, + "ruleRelevant": false, + "minValue": 0, + "maxValue": 1000, + "eventRuleRelevant": false, + "writable": true } ] } diff --git a/elgato/elgato.pro b/elgato/elgato.pro index e2a0a1e5..134e8cff 100644 --- a/elgato/elgato.pro +++ b/elgato/elgato.pro @@ -5,12 +5,10 @@ TARGET = $$qtLibraryTarget(nymea_devicepluginelgato) SOURCES += \ devicepluginelgato.cpp \ aveabulb.cpp \ - aveacolor.cpp HEADERS += \ devicepluginelgato.h \ aveabulb.h \ - aveacolor.h