From cd1b39cd375302feefa3cc67650440f5dfae78b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 20 Dec 2017 18:11:10 +0100 Subject: [PATCH] Adjust plugins to migrated hardware manager --- awattar/devicepluginawattar.h | 1 + datetime/deviceplugindatetime.h | 1 + elgato/aveabulb.cpp | 633 ++++-------------------- elgato/aveabulb.h | 77 +-- elgato/aveacolor.cpp | 70 +++ elgato/aveacolor.h | 39 ++ elgato/commandrequest.cpp | 54 -- elgato/commandrequest.h | 50 -- elgato/devicepluginelgato.cpp | 186 ++----- elgato/devicepluginelgato.h | 14 +- elgato/devicepluginelgato.json | 86 +--- elgato/elgato.pro | 4 +- elro/devicepluginelro.cpp | 2 +- guh-plugins.pro | 2 +- intertechno/devicepluginintertechno.cpp | 2 +- orderbutton/devicepluginorderbutton.h | 1 + osdomotics/devicepluginosdomotics.h | 1 + plantcare/devicepluginplantcare.h | 1 + plugins.pri | 5 - wemo/devicepluginwemo.h | 2 + ws2812/devicepluginws2812.h | 1 + 21 files changed, 322 insertions(+), 910 deletions(-) create mode 100644 elgato/aveacolor.cpp create mode 100644 elgato/aveacolor.h delete mode 100644 elgato/commandrequest.cpp delete mode 100644 elgato/commandrequest.h diff --git a/awattar/devicepluginawattar.h b/awattar/devicepluginawattar.h index a13aa6ce..e388d072 100644 --- a/awattar/devicepluginawattar.h +++ b/awattar/devicepluginawattar.h @@ -32,6 +32,7 @@ #include #include #include +#include class DevicePluginAwattar : public DevicePlugin { diff --git a/datetime/deviceplugindatetime.h b/datetime/deviceplugindatetime.h index bad2f824..bb901b6c 100644 --- a/datetime/deviceplugindatetime.h +++ b/datetime/deviceplugindatetime.h @@ -31,6 +31,7 @@ #include #include #include +#include class DevicePluginDateTime : public DevicePlugin { diff --git a/elgato/aveabulb.cpp b/elgato/aveabulb.cpp index e669d344..06f203c9 100644 --- a/elgato/aveabulb.cpp +++ b/elgato/aveabulb.cpp @@ -18,562 +18,147 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#ifdef BLUETOOTH_LE - #include "aveabulb.h" #include "extern-plugininfo.h" -AveaBulb::AveaBulb(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType, QObject *parent) : - BluetoothLowEnergyDevice(deviceInfo, addressType, parent), - m_colorService(0), - m_imageService(0), - m_queueRunning(false), - m_brigthness("57ff0f"), - m_liveliness("493300") +AveaBulb::AveaBulb(Device *device, BluetoothLowEnergyDevice *bluetoothDevice, QObject *parent) : + QObject(parent), + m_device(device), + m_bluetoothDevice(bluetoothDevice) { - m_colorSeviceUuid = QBluetoothUuid(QUuid("f815e810-456c-6761-746f-4d756e696368")); - m_colorCharacteristicUuid = QBluetoothUuid(QUuid("f815e811-456c-6761-746f-4d756e696368")); - - m_imageSeviceUuid = QBluetoothUuid(QUuid("f815e500-456c-6761-746f-4d756e696368")); - m_imageCharacteristicUuid = QBluetoothUuid(QUuid("f815e501-456c-6761-746f-4d756e696368")); - - connect(this, SIGNAL(connectionStatusChanged()), this,SLOT(onConnectionStatusChanged())); - connect(this, SIGNAL(servicesDiscoveryFinished()), this, SLOT(serviceScanFinished())); + connect(m_bluetoothDevice, &BluetoothLowEnergyDevice::connectedChanged, this, &AveaBulb::onConnectedChanged); + connect(m_bluetoothDevice, &BluetoothLowEnergyDevice::servicesDiscoveryFinished, this, &AveaBulb::onServiceDiscoveryFinished); } -bool AveaBulb::isAvailable() +Device *AveaBulb::device() { - return m_isAvailable; + return m_device; } -void AveaBulb::serviceScanFinished() +BluetoothLowEnergyDevice *AveaBulb::bluetoothDevice() { - if (!controller()->services().contains(m_colorSeviceUuid)) { - qCWarning(dcElgato) << "ERROR: Color service not found for device" << name() << address().toString(); + return m_bluetoothDevice; +} + +bool AveaBulb::setColor(const QColor &color) +{ + if (!m_bluetoothDevice->connected()) + return false; + + if (!m_colorService) + return false; + + // Convert rgb to wrgb + QByteArray command; + command.append(QByteArray::fromHex("35")); + + qCDebug(dcElgato()) << color << command; + + return true; +} + +void AveaBulb::onConnectedChanged(const bool &connected) +{ + qCDebug(dcElgato()) << "Bulb" << m_bluetoothDevice->name() << m_bluetoothDevice->address().toString() << (connected ? "connected" : "disconnected"); + m_device->setStateValue(connectedStateTypeId, connected); + + if (!connected) { + // Clean up services + m_colorService->deleteLater(); + //m_imageService->deleteLater(); + + m_colorService = nullptr; + m_imageService = nullptr; + } + +} + +void AveaBulb::onServiceDiscoveryFinished() +{ + qCDebug(dcElgato()) << "Service discovery finished"; + + if (!m_bluetoothDevice->serviceUuids().contains(colorServiceUuid)) { + qCWarning(dcElgato()) << "Could not find color service"; return; } - if (m_colorService || m_imageService) { - qCWarning(dcElgato) << "ERROR: Attention! bad implementation of service handling!!"; + if (!m_bluetoothDevice->serviceUuids().contains(imageServiceUuid)) { + qCWarning(dcElgato()) << "Could not find image service"; return; } - // service for colors - m_colorService = controller()->createServiceObject(m_colorSeviceUuid, this); - + // Color service if (!m_colorService) { - qCWarning(dcElgato) << "ERROR: could not create color service for device" << name() << address().toString(); - return; - } - - connect(m_colorService, SIGNAL(stateChanged(QLowEnergyService::ServiceState)), this, SLOT(serviceStateChanged(QLowEnergyService::ServiceState))); - connect(m_colorService, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), this, SLOT(serviceCharacteristicChanged(QLowEnergyCharacteristic, QByteArray))); - connect(m_colorService, SIGNAL(characteristicWritten(QLowEnergyCharacteristic, QByteArray)), this, SLOT(confirmedCharacteristicWritten(QLowEnergyCharacteristic, QByteArray))); - connect(m_colorService, SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)), this, SLOT(confirmedDescriptorWritten(QLowEnergyDescriptor, QByteArray))); - connect(m_colorService, SIGNAL(error(QLowEnergyService::ServiceError)), this, SLOT(serviceError(QLowEnergyService::ServiceError))); - - // service for images - m_imageService = controller()->createServiceObject(m_imageSeviceUuid, this); - - if (!m_imageService) { - qCWarning(dcElgato) << "ERROR: could not create color service for device" << name() << address().toString(); - return; - } - - connect(m_imageService, SIGNAL(stateChanged(QLowEnergyService::ServiceState)), this, SLOT(serviceStateChanged(QLowEnergyService::ServiceState))); - connect(m_imageService, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), this, SLOT(serviceCharacteristicChanged(QLowEnergyCharacteristic, QByteArray))); - connect(m_imageService, SIGNAL(characteristicWritten(QLowEnergyCharacteristic, QByteArray)), this, SLOT(confirmedCharacteristicWritten(QLowEnergyCharacteristic, QByteArray))); - connect(m_imageService, SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)), this, SLOT(confirmedDescriptorWritten(QLowEnergyDescriptor, QByteArray))); - connect(m_imageService, SIGNAL(error(QLowEnergyService::ServiceError)), this, SLOT(serviceError(QLowEnergyService::ServiceError))); - - m_colorService->discoverDetails(); -} - -void AveaBulb::onConnectionStatusChanged() -{ - if (!isConnected()) { - // delete the services, they need to be recreated and - // rediscovered once the device will be reconnected - delete m_colorService; - m_colorService = 0; - - delete m_imageService; - m_imageService = 0; - - m_commandQueue.clear(); - - m_isAvailable = false; - emit availableChanged(); - } -} - -void AveaBulb::serviceStateChanged(const QLowEnergyService::ServiceState &state) -{ - QLowEnergyService *service =static_cast(sender()); - - switch (state) { - case QLowEnergyService::DiscoveringServices: - if (service->serviceUuid() == m_colorService->serviceUuid()) { - qCDebug(dcElgato) << "start discovering color service..."; - } else if (service->serviceUuid() == m_imageService->serviceUuid()) { - qCDebug(dcElgato) << "start discovering image service..."; - } - break; - case QLowEnergyService::ServiceDiscovered: - // check which service is discovered - if (service->serviceUuid() == m_colorService->serviceUuid()) { - qCDebug(dcElgato) << "...color service discovered."; - - m_colorCharacteristic = m_colorService->characteristic(m_colorCharacteristicUuid); - - if (!m_colorCharacteristic.isValid()) { - qCWarning(dcElgato) << "ERROR: color characteristc not found for device " << name() << address().toString(); - return; - } - - m_imageService->discoverDetails(); - } - if (service->serviceUuid() == m_imageService->serviceUuid()) { - qCDebug(dcElgato) << "...image service discovered."; - - m_imageCharacteristic = m_imageService->characteristic(m_imageCharacteristicUuid); - - if (!m_imageCharacteristic.isValid()) { - qCWarning(dcElgato) << "ERROR: image characteristc not found for device " << name() << address().toString(); - return; - } + m_colorService = m_bluetoothDevice->controller()->createServiceObject(colorServiceUuid, this); + if (!m_colorService) { + qCWarning(dcElgato()) << "Could not create color service."; + return; } - if (m_colorService->state() == QLowEnergyService::ServiceDiscovered && m_imageService->state() == QLowEnergyService::ServiceDiscovered) { - m_isAvailable = true; - emit availableChanged(); - } - break; - default: - break; - } -} + connect(m_colorService, &QLowEnergyService::stateChanged, this, &AveaBulb::onColorServiceStateChanged); + connect(m_colorService, &QLowEnergyService::characteristicChanged, this, &AveaBulb::onColorServiceCharacteristicChanged); -void AveaBulb::serviceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value) -{ - qCDebug(dcElgato) << "service characteristic changed" << characteristic.name() << value.toHex(); -} - -void AveaBulb::confirmedCharacteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value) -{ - if (characteristic.handle() == m_colorCharacteristic.handle()) { - //qCDebug(dcElgato) << "color char written successfully" << value.toHex(); - if (m_actions.contains(value.toHex())) { - ActionId actionId = m_actions.take(value.toHex()); - emit actionExecutionFinished(actionId, true); - } - } else if (characteristic.handle() == m_imageCharacteristic.handle()) { - //qCDebug(dcElgato) << "image char written successfully" << value.toHex(); - if (m_actions.contains(value.toHex())) { - ActionId actionId = m_actions.take(value.toHex()); - emit actionExecutionFinished(actionId, true); - } - } - if (characteristic.uuid() == m_currentRequest.characteristic().uuid()) { - if (m_commandQueue.isEmpty()) { - m_queueRunning = false; - //qCDebug(dcElgato) << "queue finished"; - } - sendNextCommand(); - } -} - -void AveaBulb::confirmedDescriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value) -{ - qCDebug(dcElgato) << "descriptor:" << descriptor.name() << "value:" << value.toHex() << "written successfully"; -} - -void AveaBulb::serviceError(const QLowEnergyService::ServiceError &error) -{ - QString errorString; - switch (error) { - case QLowEnergyService::NoError: - errorString = "No error"; - break; - case QLowEnergyService::OperationError: - errorString = "Operation error"; - break; - case QLowEnergyService::CharacteristicWriteError: - errorString = "Characteristic write error"; - break; - case QLowEnergyService::DescriptorWriteError: - errorString = "Descriptor write error"; - break; - default: - break; + m_colorService->discoverDetails(); } - qCWarning(dcElgato) << "ERROR: color service of " << name() << address().toString() << ":" << errorString; } -void AveaBulb::enqueueCommand(QLowEnergyService *service, const QLowEnergyCharacteristic &characteristic, const QByteArray &value) +void AveaBulb::onColorServiceStateChanged(const QLowEnergyService::ServiceState &state) { - CommandRequest r = CommandRequest(service, characteristic, QByteArray::fromHex(value)); - m_commandQueue.enqueue(r); -} - -void AveaBulb::sendNextCommand() -{ - if (!isAvailable()) { - m_commandQueue.clear(); - return; - } - - if (m_commandQueue.isEmpty()) + // Only continue if discovered + if (state != QLowEnergyService::ServiceDiscovered) return; - //qCDebug(dcElgato) << "send next command"; - m_queueRunning = true; - m_currentRequest = m_commandQueue.dequeue(); + qCDebug(dcElgato()) << "Color service discovered."; + foreach (const QLowEnergyCharacteristic &characteristic, m_colorService->characteristics()) { + qCDebug(dcElgato()) << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value(); + foreach (const QLowEnergyDescriptor &desciptor, characteristic.descriptors()) { + qCDebug(dcElgato()) << " -->" << desciptor.name() << desciptor.uuid().toString() << desciptor.value(); + } + } + + // Data characteristic + m_colorCharacteristic = m_colorService->characteristic(QBluetoothUuid(QUuid("f815e811-456c-6761-746f-4d756e696368"))); + if (!m_colorCharacteristic.isValid()) { + qCWarning(dcElgato()) << "Invalid color data characteristic."; + } + + // Enable notifications + 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")); - QLowEnergyService *service = m_currentRequest.service(); - service->writeCharacteristic(m_currentRequest.characteristic(), m_currentRequest.value()); } -bool AveaBulb::actionPowerOff(ActionId actionId) +void AveaBulb::onColorServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value) { - if (!isAvailable()) - return false; + qCDebug(dcElgato()) << "Color characteristic changed" << characteristic.uuid().toString() << value; - QByteArray value = "35f4010a00008000b000a00090"; - m_actions.insert(value, actionId); - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); - - return true; + 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); + } } -bool AveaBulb::setWhite(ActionId actionId) -{ - // warm white 3514000a00ff0f703bd2259d11 - // cool white 3514000a00ff0f0030a220a31f - - if (!isAvailable()) - return false; - - QByteArray value = "3532000a00ff8f00b058a4899d"; - m_actions.insert(value, actionId); - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); - - return true; -} - -bool AveaBulb::setRed(ActionId actionId) -{ - if (!isAvailable()) - return false; - - QByteArray value = "3532000a000080ffbf00a0b390"; - m_actions.insert(value, actionId); - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); - - return true; -} - -bool AveaBulb::setGreen(ActionId actionId) -{ - if (!isAvailable()) - return false; - - QByteArray value = "3514000a00a3005231ff2f0010"; - m_actions.insert(value, actionId); - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); - - return true; -} - -bool AveaBulb::setBlue(ActionId actionId) -{ - if (!isAvailable()) - return false; - - QByteArray value = "3532000a00c8805fb6ada2ff9f"; - m_actions.insert(value, actionId); - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); - - return true; -} - -bool AveaBulb::setYellow(ActionId actionId) -{ - if (!isAvailable()) - return false; - - QByteArray value = "3532000a001481e2bfffaf0090"; - m_actions.insert(value, actionId); - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); - - return true; -} - -bool AveaBulb::setPurple(ActionId actionId) -{ - if (!isAvailable()) - return false; - - QByteArray value = "3532000a000080f6b700a02498"; - m_actions.insert(value, actionId); - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); - - return true; -} - -bool AveaBulb::setOrange(ActionId actionId) -{ - if (!isAvailable()) - return false; - - QByteArray value = "3532000a000080ffbf36aa0090"; - m_actions.insert(value, actionId); - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); - - return true; -} - -bool AveaBulb::setCalmProvence(ActionId actionId) -{ - if (!isAvailable()) - return false; - - enqueueCommand(m_colorService, m_colorCharacteristic, m_brigthness); - enqueueCommand(m_colorService, m_colorCharacteristic, m_liveliness); - enqueueCommand(m_colorService, m_colorCharacteristic, "340040203300208017"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1500cd0110cd1280811543016100a40acd00" - "20cd0040f1f80773027302f200507df13403" - "7202f200507db1147400b50af200608d0a7d" - "0ecd16a0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1600cd0210cd1280811543016100a40af1f8" - "077302f200507df1c4097202f200507db128" - "7301f200608d0a7d0ef134037202f200507d" - "b13c7301f200607d8d0a0ecdd453cd4036b1" - "c87400b50af200607d8d0a0ecd17a0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1700cd0310cd1280811543016100a40af1cc" - "017202f200507df1f8077302f200507db16e" - "7400b50af200607d8d0a0ecd18a0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1800cd0410cd1280811543016100a40af1d4" - "037202f200507db15a7400b50af200607d8d" - "0a0ef134037202f200507df1f807f200507d" - "b1c87400b50af200607d8d0a0ecd15a0"); - - enqueueCommand(m_colorService, m_colorCharacteristic, "2a15"); - - m_actions.insert("2a15", actionId); - - sendNextCommand(); - return true; -} - -bool AveaBulb::setCozyFlames(ActionId actionId) -{ - if (!isAvailable()) - return false; - - enqueueCommand(m_colorService, m_colorCharacteristic, m_brigthness); - enqueueCommand(m_colorService, m_colorCharacteristic, m_liveliness); - enqueueCommand(m_colorService, m_colorCharacteristic, "340040ff3fc8200010"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1500cd0110cd0020cdff5fcdc840cd0030cd" - "14608d0a0ecd05708216c200a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1600cd0280a16e6300cd0210cdff5fcdc840" - "cd0a608d0a0ecd1ba0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1700cd0310cd02807100b464f5c4097bcdc8" - "708278c200404dcd5070823cc200604d8d0b" - "0ecdc870c200404dcd64608d0b0e0ccdff5b" - "cd0f608d0a0ecd05708216c200a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1800cd0410cdc840cd0a608d0a0ecd028071" - "00b464f5c4097bcd0072c2004082284dcd20" - "738232c200604d8d0b0e0ccdff5fcdf842f1" - "f4017400b564f200607d8d110ecd05708216" - "c200a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1900cd0280a16e6300cd0510cdff5fcdc840" - "cd0a608d0a0ecd1ba0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1a00cd0610cd0280a16e63007100b464f5c4" - "097bcd207382c844028564c200404dcd5070" - "82a0c200604d8d0b0ecdc870c200404dcd64" - "608d0b0e0ccda040cdff5bcd0a608d0a0ecd" - "15a0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1b00cd0280a16e6300cd07107100b464f5e8" - "03b3017bcdff73c22c0144028564c200404d" - "cd50708264c200604d8d0b0ecd587282c844" - "028564c200404dcd64608d0b0e0ccdff5bcd" - "05608d0a0ecd05708216c200a04d"); - - enqueueCommand(m_colorService, m_colorCharacteristic, "2a15"); - - m_actions.insert("2a15", actionId); - - sendNextCommand(); - return true; -} - -bool AveaBulb::setCherryBlossom(ActionId actionId) -{ - if (!isAvailable()) - return false; - - enqueueCommand(m_colorService, m_colorCharacteristic, m_brigthness); - enqueueCommand(m_colorService, m_colorCharacteristic, m_liveliness); - enqueueCommand(m_colorService, m_colorCharacteristic, "346c47483d00207013"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1500cd0110cd128081654301cd0040cd5c23" - "cd7033f19e0c7201f200507db1507201f200" - "607d8d0a0ecd1aa0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1600cd0210cd128081654301f108077201f2" - "00207df1660d7201f200507df104017301f2" - "00608d0a7d0e8d0a0ecdc023b1aa7301f200" - "608d0a7d0eb16e73007ecd17a0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1700cd0310cd128081654301cd782acd9838" - "b1967301f200608d0a7d0ef1780a7301f200" - "207df1280f7201f200507db1dc7301f20060" - "8d0a7d0ecd5827cd7033b1967301f200608d" - "0a7d0ecd18a0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1800cd0410cd128081654301cd6c27cd345d" - "b1a07301f200608d0a7d0ecdc023b1b47301" - "f200608d0a7d0ecd402bcd6039b1a07301f2" - "00607d8d0a0ecdc023cdf05fb1a07301f200" - "607d8d0a0ecd19a0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1900cd0410cd128081654301cd502acd7033" - "b1a07301f200608d0a7d0ecd1aa0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1a00cd0510cd128081654301cd2033cdcc21" - "7101b20af200607d8d0a0ecd04708216c200" - "a04d"); - - enqueueCommand(m_colorService, m_colorCharacteristic, "2a15"); - - m_actions.insert("2a15", actionId); - - sendNextCommand(); - return true; -} - -bool AveaBulb::setMountainBreeze(ActionId actionId) -{ - if (!isAvailable()) - return false; - - enqueueCommand(m_colorService, m_colorCharacteristic, m_brigthness); - enqueueCommand(m_colorService, m_colorCharacteristic, m_liveliness); - enqueueCommand(m_colorService, m_colorCharacteristic, "34584200300020ff1f"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1500cd0110cd5822cd0050cd0040cdff3fcd" - "14608d0a0ecd03708216c200a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1600cd0210cd1280a1646301cd9828f16801" - "7402b564f200608d0a7d0ecd5822f1040174" - "02b564f200608d0a7d0ecd03708216c200a0" - "4d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1700cd0310cd1280a1646301cd283acd4c24" - "cddc70825044028564c200608d0a4d0ecda0" - "20cddc70825044028564c200604d8d0a0ecd" - "03708216c200a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1800cd0410cd1280a1646301f178057302f2" - "00207df12c017402b564f200608d0a7d0ecd" - "2023f1480d7302f200307df178057302f200" - "207dcdb470825044028564c200604d8d0a0e" - "cd03708216c200a04d"); - enqueueCommand(m_colorService, m_colorCharacteristic, "2a15"); - - m_actions.insert("2a15", actionId); - - sendNextCommand(); - return true; -} - -bool AveaBulb::setNorthernGlow(ActionId actionId) -{ - if (!isAvailable()) - return false; - - enqueueCommand(m_colorService, m_colorCharacteristic, m_brigthness); - enqueueCommand(m_colorService, m_colorCharacteristic, m_liveliness); - enqueueCommand(m_colorService, m_colorCharacteristic, "34004000301420e011"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1500cd1280cd0110cd0020cd0050cd1440cd" - "e031cd14608d0a0ecdf07082e64201c20030" - "4db1b47301f200607d8d0a0ecd04708216c2" - "00a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1600cd0210cd1280b1a07301f200607dcd50" - "7082504301c200404dcdf070c2b8014201c2" - "00304d8d0a0ecd03708217c200a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1700cd0310cd1280b1967301f200607dcd2c" - "40cd0050cdb4308d0a0ecd04708216c200a0" - "4d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1800cd0410cd1280b1aa7301f200607dcd50" - "70821ec200404dcd0050c168014201c20030" - "4d8d0a0ecd04708216c200a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1900cd0510cd1280b1a07301f200607de170" - "08e31c026401a564f170087302f200407dcd" - "28308d110eb1a07301f200607df1f8027200" - "f200407dcd28308d110ecddc70823c4301c2" - "00604dcd3c40cda0308d0a0ecd15a0"); - - enqueueCommand(m_colorService, m_colorCharacteristic, "2a15"); - - m_actions.insert("2a15", actionId); - - sendNextCommand(); - return true; -} - -bool AveaBulb::setFairyWoods(ActionId actionId) -{ - if (!isAvailable()) - return false; - - enqueueCommand(m_colorService, m_colorCharacteristic, "57ff0f"); - enqueueCommand(m_colorService, m_colorCharacteristic, "340040143058220010"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1500cd0110cd0020cd0030cd2850cd5842cd" - "14608d0a0ecd04708216c200a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1600cd0210cd1280a1646301cd14608d080e" - "cd9041f190017402b564f200608d0a7d0ecd" - "6851b1c87402b564f200608d0a7d0ecdff47" - "cd6450cdb470823c44028564c200604d8d0a" - "0ecd17a0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1700cd0310cd1280a1646301cde041cd2850" - "b1f07402b564f200608d0a7d0ecd04708216" - "c200a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1800cd0410cd1280a1646301cdb841cdb470" - "823c7402b564c200604d8d0a0ecd0e41cd28" - "50b1c87402b564f200608d0a7d0ecd6440f1" - "90017402b564f200608d0a7d0e8d0a0ecd04" - "708216c200a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1900cd0510cd1280a1646301cd6841cdb470" - "823cc200604d8d0a0ecda050f12c017402b5" - "64f200608d0a7d0ecdf040cd2850f1680174" - "02b564f200608d0a7d0ecdcc41b1c87402b5" - "64f200608d0a7d0ecd04708216c200a04d"); - enqueueCommand(m_colorService, m_colorCharacteristic, "2a15"); - - m_actions.insert("2a15", actionId); - - sendNextCommand(); - return true; -} - -bool AveaBulb::setMagicHour(ActionId actionId) -{ - if (!isAvailable()) - return false; - - enqueueCommand(m_colorService, m_colorCharacteristic, m_brigthness); - enqueueCommand(m_colorService, m_colorCharacteristic, m_liveliness); - enqueueCommand(m_colorService, m_colorCharacteristic, "340040d03c90210010"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1500cd0110cd0020cdd05ccd9041cd0030cd" - "14608d0a0ecd02708216c200a04d"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1600cd0210cd0a60cd0030cd0020cd29408d" - "0a0ecd128081664301e1ff0fe3ff07a50a64" - "01a50a5100cd0a706400a50af1ff0f7302f2" - "00507dcd28708229c200404dcd32704201c2" - "00604d8d0a0ecd17a0"); - enqueueCommand(m_imageService, m_imageCharacteristic, "1700cd0310cd1460cd0030cd00208d0a0ecd" - "1280a16663018d0d85808250c200404dcd32" - "70820a4202c200604d8d0a0ecd16a0"); - enqueueCommand(m_colorService, m_colorCharacteristic, "2a15"); - - m_actions.insert("2a15", actionId); - - sendNextCommand(); - return true; -} - -#endif // BLUETOOTH_LE diff --git a/elgato/aveabulb.h b/elgato/aveabulb.h index f6e8debe..d2028939 100644 --- a/elgato/aveabulb.h +++ b/elgato/aveabulb.h @@ -21,84 +21,47 @@ #ifndef AVEABULB_H #define AVEABULB_H -#ifdef BLUETOOTH_LE - #include #include +#include #include "typeutils.h" -#include "bluetooth/bluetoothlowenergydevice.h" -#include "commandrequest.h" +#include "plugin/device.h" +#include "hardware/bluetoothlowenergy/bluetoothlowenergydevice.h" -class AveaBulb : public BluetoothLowEnergyDevice +static QBluetoothUuid colorServiceUuid = QBluetoothUuid(QUuid("f815e810-456c-6761-746f-4d756e696368")); +static QBluetoothUuid imageServiceUuid = QBluetoothUuid(QUuid("f815e500-456c-6761-746f-4d756e696368")); + +class AveaBulb : public QObject { Q_OBJECT public: - explicit AveaBulb(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType, QObject *parent = 0); + explicit AveaBulb(Device *device, BluetoothLowEnergyDevice *bluetoothDevice, QObject *parent = nullptr); - bool isAvailable(); + Device *device(); + BluetoothLowEnergyDevice *bluetoothDevice(); -signals: - void availableChanged(); - void actionExecutionFinished(const ActionId &actionId, const bool &success); + bool setColor(const QColor &color); private: - QBluetoothUuid m_colorSeviceUuid; - QLowEnergyService *m_colorService; + Device *m_device; + BluetoothLowEnergyDevice *m_bluetoothDevice; - QBluetoothUuid m_imageSeviceUuid; - QLowEnergyService *m_imageService; +private: + QLowEnergyService *m_colorService = nullptr; + QLowEnergyService *m_imageService = nullptr; - QBluetoothUuid m_imageCharacteristicUuid; QLowEnergyCharacteristic m_imageCharacteristic; - - QBluetoothUuid m_colorCharacteristicUuid; QLowEnergyCharacteristic m_colorCharacteristic; - bool m_isAvailable; - - QHash m_actions; - - QQueue m_commandQueue; - CommandRequest m_currentRequest; - bool m_queueRunning; - - QByteArray m_brigthness; - QByteArray m_liveliness; - private slots: - void serviceScanFinished(); - void onConnectionStatusChanged(); + void onConnectedChanged(const bool &connected); + void onServiceDiscoveryFinished(); // Color service - void serviceStateChanged(const QLowEnergyService::ServiceState &state); - void serviceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value); - void confirmedCharacteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value); - void confirmedDescriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value); - void serviceError(const QLowEnergyService::ServiceError &error); - - void enqueueCommand(QLowEnergyService *service, const QLowEnergyCharacteristic &characteristic, const QByteArray &value); - void sendNextCommand(); - -public slots: - bool actionPowerOff(ActionId actionId); - bool setWhite(ActionId actionId); - bool setRed(ActionId actionId); - bool setGreen(ActionId actionId); - bool setBlue(ActionId actionId); - bool setYellow(ActionId actionId); - bool setPurple(ActionId actionId); - bool setOrange(ActionId actionId); - - bool setCalmProvence(ActionId actionId); - bool setCozyFlames(ActionId actionId); - bool setCherryBlossom(ActionId actionId); - bool setMountainBreeze(ActionId actionId); - bool setNorthernGlow(ActionId actionId); - bool setFairyWoods(ActionId actionId); - bool setMagicHour(ActionId actionId); + void onColorServiceStateChanged(const QLowEnergyService::ServiceState &state); + void onColorServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value); }; -#endif // BLUETOOTH_LE #endif // AVEABULB_H diff --git a/elgato/aveacolor.cpp b/elgato/aveacolor.cpp new file mode 100644 index 00000000..df3da5b4 --- /dev/null +++ b/elgato/aveacolor.cpp @@ -0,0 +1,70 @@ +#include "aveacolor.h" + +AveaColor::AveaColor(const QColor &color) +{ + // Convert rgb to wrgb + + ColorRgbw rgbw = rgbToRgbw(color.red(), color.green(), color.blue()); + Q_UNUSED(rgbw) + +} + +uint AveaColor::white() const +{ + return m_white; +} + +uint AveaColor::red() const +{ + return m_red; +} + +uint AveaColor::green() const +{ + return m_green; +} + +uint AveaColor::blue() const +{ + return m_blue; +} + +QByteArray AveaColor::toByteArray() +{ + return QByteArray(); +} + +// The saturation is the colorfulness of a color relative to its own brightness. +uint AveaColor::saturation(ColorRgbw rgbw) +{ + // Find the smallest of all three parameters. + float low = qMin(rgbw.red, qMin(rgbw.green, rgbw.blue)); + // Find the highest of all three parameters. + float high = qMax(rgbw.red, qMax(rgbw.green, rgbw.blue)); + // The difference between the last two variables + // divided by the highest is the saturation. + return qRound(100 * ((high - low) / high)); +} + +uint AveaColor::getWhite(ColorRgbw rgbw) +{ + return (255 - saturation(rgbw)) / 255 * (rgbw.red + rgbw.green + rgbw.blue) / 3; +} + +uint AveaColor::getWhite(ColorRgbw rgbw, int redMax, int greenMax, int blueMax) +{ + // Set the maximum value for all colors. + rgbw.red = (float)rgbw.red / 255.0 * (float)redMax; + rgbw.green = (float)rgbw.green / 255.0 * (float)greenMax; + rgbw.blue = (float)rgbw.blue / 255.0 * (float)blueMax; + return (255 - saturation(rgbw)) / 255 * (rgbw.red + rgbw.green + rgbw.blue) / 3; + return 0; +} + +ColorRgbw AveaColor::rgbToRgbw(uint red, uint green, uint blue) +{ + uint white = 0; + ColorRgbw rgbw = {red, green, blue, white}; + rgbw.white = getWhite(rgbw); + return rgbw; +} diff --git a/elgato/aveacolor.h b/elgato/aveacolor.h new file mode 100644 index 00000000..a38041b1 --- /dev/null +++ b/elgato/aveacolor.h @@ -0,0 +1,39 @@ +#ifndef AVEACOLOR_H +#define AVEACOLOR_H + +#include +#include + +struct ColorRgbw { + uint red; + uint green; + uint blue; + uint white; +}; + + +class AveaColor +{ +public: + AveaColor(const QColor &color); + + uint white() const; + uint red() const; + uint green() const; + uint blue() const; + + QByteArray toByteArray(); + +private: + uint m_white = 0; + uint m_red = 0; + uint m_green = 0; + uint m_blue = 0; + + uint saturation(ColorRgbw rgbw); + uint getWhite(ColorRgbw rgbw); + uint getWhite(ColorRgbw rgbw, int redMax, int greenMax, int blueMax); + ColorRgbw rgbToRgbw(unsigned int red, unsigned int green, unsigned int blue); +}; + +#endif // AVEACOLOR_H diff --git a/elgato/commandrequest.cpp b/elgato/commandrequest.cpp deleted file mode 100644 index 702fbe1b..00000000 --- a/elgato/commandrequest.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * This file is part of guh. * - * * - * 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 * - * . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifdef BLUETOOTH_LE - -#include "commandrequest.h" - -CommandRequest::CommandRequest() : - m_service(0), - m_characteristic(QLowEnergyCharacteristic()), - m_value(QByteArray()) -{ -} - -CommandRequest::CommandRequest(QLowEnergyService *service, const QLowEnergyCharacteristic &characteristic, const QByteArray &value) : - m_service(service), - m_characteristic(characteristic), - m_value(value) -{ -} - -QLowEnergyService *CommandRequest::service() -{ - return m_service; -} - -QLowEnergyCharacteristic CommandRequest::characteristic() const -{ - return m_characteristic; -} - -QByteArray CommandRequest::value() const -{ - return m_value; -} - -#endif // BLUETOOTH_LE diff --git a/elgato/commandrequest.h b/elgato/commandrequest.h deleted file mode 100644 index cf757073..00000000 --- a/elgato/commandrequest.h +++ /dev/null @@ -1,50 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * This file is part of guh. * - * * - * 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 COMMANDREQUEST_H -#define COMMANDREQUEST_H - -#ifdef BLUETOOTH_LE - -#include -#include -#include - -class CommandRequest -{ - -public: - CommandRequest(); - CommandRequest(QLowEnergyService *service, const QLowEnergyCharacteristic &characteristic, const QByteArray &value); - - QLowEnergyService *service(); - QLowEnergyCharacteristic characteristic() const; - QByteArray value() const; - -private: - QLowEnergyService *m_service; - QLowEnergyCharacteristic m_characteristic; - QByteArray m_value; - -}; - -#endif // BLUETOOTH_LE - -#endif // COMMANDREQUEST_H diff --git a/elgato/devicepluginelgato.cpp b/elgato/devicepluginelgato.cpp index c0c1dacd..b21f3140 100644 --- a/elgato/devicepluginelgato.cpp +++ b/elgato/devicepluginelgato.cpp @@ -396,16 +396,16 @@ \quotefile plugins/deviceplugins/elgato/devicepluginelgato.json */ -#ifdef BLUETOOTH_LE - #include "devicepluginelgato.h" #include "plugin/device.h" #include "devicemanager.h" #include "plugininfo.h" +#include "hardware/bluetoothlowenergy/bluetoothlowenergymanager.h" DevicePluginElgato::DevicePluginElgato() { + } DeviceManager::DeviceError DevicePluginElgato::discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) @@ -415,155 +415,70 @@ DeviceManager::DeviceError DevicePluginElgato::discoverDevices(const DeviceClass if (deviceClassId != aveaDeviceClassId) return DeviceManager::DeviceErrorDeviceClassNotFound; - if (!discoverBluetooth()) + if (!hardwareManager()->bluetoothLowEnergyManager()->available()) return DeviceManager::DeviceErrorHardwareNotAvailable; + if (!hardwareManager()->bluetoothLowEnergyManager()->enabled()) + return DeviceManager::DeviceErrorHardwareNotAvailable; + + BluetoothDiscoveryReply *reply = hardwareManager()->bluetoothLowEnergyManager()->discoverDevices(); + connect(reply, &BluetoothDiscoveryReply::finished, this, &DevicePluginElgato::onBluetoothDiscoveryFinished); return DeviceManager::DeviceErrorAsync; } DeviceManager::DeviceSetupStatus DevicePluginElgato::setupDevice(Device *device) { + qCDebug(dcElgato()) << "Setup device" << device->name() << device->params(); + if (device->deviceClassId() == aveaDeviceClassId) { QBluetoothAddress address = QBluetoothAddress(device->paramValue(macAddressParamTypeId).toString()); QString name = device->paramValue(nameParamTypeId).toString(); QBluetoothDeviceInfo deviceInfo = QBluetoothDeviceInfo(address, name, 0); - AveaBulb *avea = new AveaBulb(deviceInfo, QLowEnergyController::PublicAddress, this); - connect(avea, &AveaBulb::availableChanged, this, &DevicePluginElgato::bulbAvailableChanged); - connect(avea, &AveaBulb::actionExecutionFinished, this, &DevicePluginElgato::actionFinished); - m_bulbs.insert(avea, device); + BluetoothLowEnergyDevice *bluetoothDevice = hardwareManager()->bluetoothLowEnergyManager()->registerDevice(deviceInfo, QLowEnergyController::PublicAddress); - avea->connectDevice(); + AveaBulb *bulb = new AveaBulb(device, bluetoothDevice, this); + + m_bulbs.insert(device, bulb); + bulb->bluetoothDevice()->connectDevice(); return DeviceManager::DeviceSetupStatusSuccess; } return DeviceManager::DeviceSetupStatusFailure; } -DeviceManager::HardwareResources DevicePluginElgato::requiredHardware() const -{ - return DeviceManager::HardwareResourceBluetoothLE; -} - DeviceManager::DeviceError DevicePluginElgato::executeAction(Device *device, const Action &action) { + Q_UNUSED(action) // check deviceClassId if (device->deviceClassId() == aveaDeviceClassId) { - AveaBulb *bulb = m_bulbs.key(device); + AveaBulb *bulb = m_bulbs.value(device); - // reconnect action does not need available true - if (action.actionTypeId() == connectActionTypeId) { - bulb->reconnectDevice(); - return DeviceManager::DeviceErrorNoError; - } + Q_UNUSED(bulb) +// // check actionTypeId +// if (action.actionTypeId() == powerOffActionTypeId) { +// bulb->actionPowerOff(action.id()); +// return DeviceManager::DeviceErrorAsync; +// } else if (action.actionTypeId() == colorActionTypeId) { - if (action.actionTypeId() == disconnectActionTypeId) { - bulb->disconnectDevice(); - return DeviceManager::DeviceErrorNoError; - } +// return DeviceManager::DeviceErrorNoError; +// } - // check available - if (!bulb->isAvailable()) - return DeviceManager::DeviceErrorHardwareNotAvailable; - - // check actionTypeId - if (action.actionTypeId() == powerOffActionTypeId) { - bulb->actionPowerOff(action.id()); - return DeviceManager::DeviceErrorAsync; - } else if (action.actionTypeId() == colorActionTypeId) { - if (action.param(colorParamTypeId).value().toString() == "green") { - bulb->setGreen(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(colorParamTypeId).value().toString() == "blue") { - bulb->setBlue(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(colorParamTypeId).value().toString() == "red") { - bulb->setRed(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(colorParamTypeId).value().toString() == "yellow") { - bulb->setYellow(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(colorParamTypeId).value().toString() == "orange") { - bulb->setOrange(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(colorParamTypeId).value().toString() == "purple") { - bulb->setPurple(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(colorParamTypeId).value().toString() == "white") { - bulb->setWhite(action.id()); - return DeviceManager::DeviceErrorAsync; - } - return DeviceManager::DeviceErrorInvalidParameter; - } else if (action.actionTypeId() == moodActionTypeId) { - if (action.param(moodParamTypeId).value().toString() == "calm provence") { - bulb->setCalmProvence(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(moodParamTypeId).value().toString() == "cozy flames") { - bulb->setCozyFlames(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(moodParamTypeId).value().toString() == "cherry blossom") { - bulb->setCherryBlossom(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(moodParamTypeId).value().toString() == "mountain breeze") { - bulb->setMountainBreeze(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(moodParamTypeId).value().toString() == "northern glow") { - bulb->setNorthernGlow(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(moodParamTypeId).value().toString() == "fairy woods") { - bulb->setFairyWoods(action.id()); - return DeviceManager::DeviceErrorAsync; - } - if (action.param(moodParamTypeId).value().toString() == "magic hour") { - bulb->setMagicHour(action.id()); - return DeviceManager::DeviceErrorAsync; - } - return DeviceManager::DeviceErrorInvalidParameter; - } return DeviceManager::DeviceErrorActionTypeNotFound; } return DeviceManager::DeviceErrorDeviceClassNotFound; } -void DevicePluginElgato::bluetoothDiscoveryFinished(const QList &deviceInfos) -{ - QList deviceDescriptors; - foreach (QBluetoothDeviceInfo deviceInfo, deviceInfos) { - if (deviceInfo.name().contains("Avea")) { - if (!verifyExistingDevices(deviceInfo)) { - DeviceDescriptor descriptor(aveaDeviceClassId, "Avea", deviceInfo.address().toString()); - ParamList params; - params.append(Param(nameParamTypeId, deviceInfo.name())); - params.append(Param(macAddressParamTypeId, deviceInfo.address().toString())); - descriptor.setParams(params); - deviceDescriptors.append(descriptor); - } - } - } - - emit devicesDiscovered(aveaDeviceClassId, deviceDescriptors); -} void DevicePluginElgato::deviceRemoved(Device *device) { - if (!m_bulbs.values().contains(device)) + if (!m_bulbs.keys().contains(device)) return; - AveaBulb *bulb= m_bulbs.key(device); - - m_bulbs.take(bulb); - delete bulb; + AveaBulb *bulb = m_bulbs.value(device); + m_bulbs.remove(device); + hardwareManager()->bluetoothLowEnergyManager()->unregisterDevice(bulb->bluetoothDevice()); + bulb->deleteLater(); } bool DevicePluginElgato::verifyExistingDevices(const QBluetoothDeviceInfo &deviceInfo) @@ -576,23 +491,32 @@ bool DevicePluginElgato::verifyExistingDevices(const QBluetoothDeviceInfo &devic return false; } -void DevicePluginElgato::bulbAvailableChanged() +void DevicePluginElgato::onBluetoothDiscoveryFinished() { - AveaBulb *bulb =static_cast(sender()); - Device *device = m_bulbs.value(bulb); - device->setStateValue(availableStateTypeId, bulb->isAvailable()); - -} - -void DevicePluginElgato::actionFinished(const ActionId actionId, const bool &success) -{ - if (success) { - emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorNoError); - } else { - emit actionExecutionFinished(actionId, DeviceManager::DeviceErrorHardwareFailure); + BluetoothDiscoveryReply *reply = static_cast(sender()); + if (reply->error() != BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorNoError) { + qCWarning(dcElgato()) << "Bluetooth discovery error:" << reply->error(); + reply->deleteLater(); + emit devicesDiscovered(aveaDeviceClassId, QList()); + return; } + + QList deviceDescriptors; + foreach (const QBluetoothDeviceInfo &deviceInfo, reply->discoveredDevices()) { + if (deviceInfo.name().contains("Avea")) { + if (!verifyExistingDevices(deviceInfo)) { + DeviceDescriptor descriptor(aveaDeviceClassId, "Avea", deviceInfo.address().toString()); + ParamList params; + params.append(Param(nameParamTypeId, deviceInfo.name())); + params.append(Param(macAddressParamTypeId, deviceInfo.address().toString())); + descriptor.setParams(params); + deviceDescriptors.append(descriptor); + } + } + } + + reply->deleteLater(); + + emit devicesDiscovered(aveaDeviceClassId, deviceDescriptors); } -#endif // BLUETOOTH_LE - - diff --git a/elgato/devicepluginelgato.h b/elgato/devicepluginelgato.h index d6213d65..7eee753f 100644 --- a/elgato/devicepluginelgato.h +++ b/elgato/devicepluginelgato.h @@ -21,10 +21,8 @@ #ifndef DEVICEPLUGINELGATO_H #define DEVICEPLUGINELGATO_H -#ifdef BLUETOOTH_LE - #include "plugin/deviceplugin.h" -#include "bluetooth/bluetoothlowenergydevice.h" +#include "hardware/bluetoothlowenergy/bluetoothlowenergydevice.h" #include "aveabulb.h" class DevicePluginElgato : public DevicePlugin @@ -39,20 +37,16 @@ public: DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList ¶ms) override; DeviceManager::DeviceSetupStatus setupDevice(Device *device) override; - DeviceManager::HardwareResources requiredHardware() const override; DeviceManager::DeviceError executeAction(Device *device, const Action &action) override; - - void bluetoothDiscoveryFinished(const QList &deviceInfos); void deviceRemoved(Device *device) override; private: - QHash m_bulbs; + QHash m_bulbs; bool verifyExistingDevices(const QBluetoothDeviceInfo &deviceInfo); private slots: - void bulbAvailableChanged(); - void actionFinished(const ActionId actionId, const bool &success); + void onBluetoothDiscoveryFinished(); + }; -#endif // BLUETOOTH_LE #endif // DEVICEPLUGINELGATO_H diff --git a/elgato/devicepluginelgato.json b/elgato/devicepluginelgato.json index 96639b82..e0fe0074 100644 --- a/elgato/devicepluginelgato.json +++ b/elgato/devicepluginelgato.json @@ -39,16 +39,16 @@ "stateTypes": [ { "id": "6d5e792a-c786-40d2-ae35-a48ac6fafcbc", - "idName": "available", - "name": "available", - "eventTypeName": "available changed", + "idName": "connected", + "name": "connected", + "eventTypeName": "connected changed", "type": "bool", "defaultValue": false }, { "id": "c38181a0-e19b-423f-8b66-dedda94e89b5", "idName": "brightness", - "name": "brightness", + "name": "Brightness", "eventTypeName": "brightness changed", "actionTypeName": "Set brightness", "type": "int", @@ -60,79 +60,17 @@ "writable": true }, { - "id": "2073b44b-2f99-4abf-8d9f-6b33be8e1763", - "idName": "liveliness", - "name": "liveliness", - "eventTypeName": "liveliness changed", - "actionTypeName": "Set liveliness", - "type": "int", - "defaultValue": 100, + "id": "3f15637a-8272-4714-bd08-04806e05bbef", + "idName": "color", + "name": "color", + "eventTypeName": "color changed", + "actionTypeName": "Set color", + "type": "QColor", "ruleRelevant": false, "eventRuleRelevant": false, - "minValue": 0, - "maxValue": 100, + "defaultValue": "#000000", "writable": true - } - ], - "actionTypes": [ - { - "id": "30b6334d-37cd-4b94-a397-3b9b642c762e", - "idName": "connect", - "name": "connect" - }, - { - "id": "1daa8def-85d7-44fb-b0bd-77a4301056e5", - "idName": "disconnect", - "name": "disconnect" - }, - { - "id": "b2f39b7b-dd11-4db4-a82b-dd3d4b973bd5", - "idName": "powerOff", - "name": "power off" - }, - { - "id": "7936bd51-7ea3-4df4-9998-7325de85b677", - "idName": "color", - "name": "set color", - "paramTypes": [ - { - "id": "f5f02666-576d-4dee-afa3-f38e1b24f469", - "idName": "color", - "name": "color", - "type": "QString", - "allowedValues": [ - "green", - "yellow", - "orange", - "red", - "purple", - "blue", - "white" - ] - } - ] - }, - { - "id": "dfbc86e8-3891-4782-ae14-05228e70423e", - "idName": "mood", - "name": "set mood", - "paramTypes": [ - { - "id": "c5d42d41-f25c-4d15-aed1-b67071847246", - "idName": "mood", - "name": "mood", - "type": "QString", - "allowedValues": [ - "calm provence", - "cozy flames", - "cherry blossom", - "mountain breeze", - "northern glow", - "fairy woods", - "magic hour" - ] - } - ] + } ] } diff --git a/elgato/elgato.pro b/elgato/elgato.pro index 3b6a4c7c..d2b5064a 100644 --- a/elgato/elgato.pro +++ b/elgato/elgato.pro @@ -9,12 +9,12 @@ TARGET = $$qtLibraryTarget(guh_devicepluginelgato) SOURCES += \ devicepluginelgato.cpp \ aveabulb.cpp \ - commandrequest.cpp + aveacolor.cpp HEADERS += \ devicepluginelgato.h \ aveabulb.h \ - commandrequest.h + aveacolor.h diff --git a/elro/devicepluginelro.cpp b/elro/devicepluginelro.cpp index 1ff828db..79064a65 100644 --- a/elro/devicepluginelro.cpp +++ b/elro/devicepluginelro.cpp @@ -55,7 +55,7 @@ DevicePluginElro::DevicePluginElro() DeviceManager::DeviceError DevicePluginElro::executeAction(Device *device, const Action &action) { - if (!hardwareManager()->isAvailable(HardwareResource::TypeRadio433)) + if (!hardwareManager()->radio433()->available()) return DeviceManager::DeviceErrorHardwareNotAvailable; if (action.actionTypeId() != powerActionTypeId) diff --git a/guh-plugins.pro b/guh-plugins.pro index f639a077..d9673735 100644 --- a/guh-plugins.pro +++ b/guh-plugins.pro @@ -20,7 +20,7 @@ PLUGIN_DIRS = \ udpcommander \ tcpcommander \ kodi \ - #elgato \ + elgato \ #senic \ awattar \ netatmo \ diff --git a/intertechno/devicepluginintertechno.cpp b/intertechno/devicepluginintertechno.cpp index 463eb777..7244a9a3 100644 --- a/intertechno/devicepluginintertechno.cpp +++ b/intertechno/devicepluginintertechno.cpp @@ -58,7 +58,7 @@ DevicePluginIntertechno::DevicePluginIntertechno() DeviceManager::DeviceError DevicePluginIntertechno::executeAction(Device *device, const Action &action) { - if (!hardwareManager()->isAvailable(HardwareResource::TypeRadio433)) + if (!hardwareManager()->radio433()->available()) return DeviceManager::DeviceErrorHardwareNotAvailable; QList rawData; diff --git a/orderbutton/devicepluginorderbutton.h b/orderbutton/devicepluginorderbutton.h index f81c2a87..fe18fd0e 100644 --- a/orderbutton/devicepluginorderbutton.h +++ b/orderbutton/devicepluginorderbutton.h @@ -30,6 +30,7 @@ #include "plugintimer.h" #include +#include class DevicePluginOrderButton : public DevicePlugin { diff --git a/osdomotics/devicepluginosdomotics.h b/osdomotics/devicepluginosdomotics.h index b0854d29..d12ccacc 100644 --- a/osdomotics/devicepluginosdomotics.h +++ b/osdomotics/devicepluginosdomotics.h @@ -27,6 +27,7 @@ #include #include +#include #include "coap/coap.h" #include "plugintimer.h" diff --git a/plantcare/devicepluginplantcare.h b/plantcare/devicepluginplantcare.h index 48aeb887..2d42b8bb 100644 --- a/plantcare/devicepluginplantcare.h +++ b/plantcare/devicepluginplantcare.h @@ -30,6 +30,7 @@ #include "plugintimer.h" #include +#include class DevicePluginPlantCare : public DevicePlugin { diff --git a/plugins.pri b/plugins.pri index f726b786..ad3f716d 100644 --- a/plugins.pri +++ b/plugins.pri @@ -11,11 +11,6 @@ LIBS += -lguh PLUGIN_PATH=/usr/lib/$$system('dpkg-architecture -q DEB_HOST_MULTIARCH')/guh/plugins/ -# Check for Bluetoot LE support (Qt >= 5.4) -equals(QT_MAJOR_VERSION, 5):greaterThan(QT_MINOR_VERSION, 3) { - DEFINES += BLUETOOTH_LE -} - # Check if this is a snap build snappy{ INCLUDEPATH+=$$(SNAPCRAFT_STAGE)/usr/include/guh diff --git a/wemo/devicepluginwemo.h b/wemo/devicepluginwemo.h index 0bc8b751..1f1861d9 100644 --- a/wemo/devicepluginwemo.h +++ b/wemo/devicepluginwemo.h @@ -26,6 +26,8 @@ #include "plugintimer.h" #include "plugin/deviceplugin.h" +#include + class DevicePluginWemo : public DevicePlugin { Q_OBJECT diff --git a/ws2812/devicepluginws2812.h b/ws2812/devicepluginws2812.h index 83a22272..eda5499c 100644 --- a/ws2812/devicepluginws2812.h +++ b/ws2812/devicepluginws2812.h @@ -31,6 +31,7 @@ #include #include +#include class DevicePluginWs2812 : public DevicePlugin {