From e0dc6f2c84319de8704d4ecbcb20f394da82d480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20St=C3=BCrz?= Date: Wed, 1 Apr 2015 13:55:11 +0200 Subject: [PATCH] experiments with avea --- libguh/bluetooth/bluetoothlowenergydevice.cpp | 12 +- libguh/bluetooth/bluetoothlowenergydevice.h | 1 + plugins/deviceplugins/elgato/aveabulb.cpp | 158 +++++++++++++++--- plugins/deviceplugins/elgato/aveabulb.h | 13 +- .../elgato/devicepluginelgato.cpp | 13 +- plugins/deviceplugins/elgato/elgato.pro | 8 +- .../deviceplugins/elgato/imagefairywoods.cpp | 6 + .../deviceplugins/elgato/imagefairywoods.h | 18 ++ 8 files changed, 198 insertions(+), 31 deletions(-) create mode 100644 plugins/deviceplugins/elgato/imagefairywoods.cpp create mode 100644 plugins/deviceplugins/elgato/imagefairywoods.h diff --git a/libguh/bluetooth/bluetoothlowenergydevice.cpp b/libguh/bluetooth/bluetoothlowenergydevice.cpp index 0cb6f6cf..2437499f 100644 --- a/libguh/bluetooth/bluetoothlowenergydevice.cpp +++ b/libguh/bluetooth/bluetoothlowenergydevice.cpp @@ -50,6 +50,12 @@ void BluetoothLowEnergyDevice::connectDevice() m_controller->connectToDevice(); } +void BluetoothLowEnergyDevice::reconnectDevice() +{ + if (!isConnected()) + m_controller->connectToDevice(); +} + void BluetoothLowEnergyDevice::disconnectDevice() { m_controller->disconnectFromDevice(); @@ -63,8 +69,9 @@ bool BluetoothLowEnergyDevice::isConnected() const void BluetoothLowEnergyDevice::connected() { m_connected = true; - qDebug() << "connected successfully to bluetooth LE device:" << name() << address().toString(); + qDebug() << "connected to bluetooth LE device:" << name() << address().toString(); emit connectionStatusChanged(); + qDebug() << "discover services..."; m_controller->discoverServices(); } @@ -77,5 +84,6 @@ void BluetoothLowEnergyDevice::disconnected() void BluetoothLowEnergyDevice::deviceError(const QLowEnergyController::Error &error) { - qWarning() << "ERROR: Bluetooth LE device:" << name() << address().toString() << ": " << error << m_controller->errorString(); + if (isConnected()) + qWarning() << "ERROR: Bluetooth LE device:" << name() << address().toString() << ": " << error << m_controller->errorString(); } diff --git a/libguh/bluetooth/bluetoothlowenergydevice.h b/libguh/bluetooth/bluetoothlowenergydevice.h index ab85a24a..cce83efb 100644 --- a/libguh/bluetooth/bluetoothlowenergydevice.h +++ b/libguh/bluetooth/bluetoothlowenergydevice.h @@ -35,6 +35,7 @@ public: QBluetoothAddress address() const; void connectDevice(); + void reconnectDevice(); void disconnectDevice(); bool isConnected() const; diff --git a/plugins/deviceplugins/elgato/aveabulb.cpp b/plugins/deviceplugins/elgato/aveabulb.cpp index 6d23b54a..8dfbd464 100644 --- a/plugins/deviceplugins/elgato/aveabulb.cpp +++ b/plugins/deviceplugins/elgato/aveabulb.cpp @@ -3,11 +3,15 @@ AveaBulb::AveaBulb(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType, QObject *parent) : BluetoothLowEnergyDevice(deviceInfo, addressType, parent), - m_colorService(0) + m_colorService(0), + m_imageService(0) { 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())); } @@ -24,12 +28,12 @@ void AveaBulb::serviceScanFinished() return; } - if (m_colorService) { + if (m_colorService || m_imageService) { qWarning() << "ERROR: Attention! bad implementation of service handling!!"; return; } - // create color service and discover it + // service for colors m_colorService = controller()->createServiceObject(m_colorSeviceUuid, this); if (!m_colorService) { @@ -38,20 +42,39 @@ void AveaBulb::serviceScanFinished() } 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(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) { + qWarning() << "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 service, needs to be recreatedand rediscovered once the device will be reconnected + // 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_isAvailable = false; emit availableChanged(); } @@ -59,16 +82,45 @@ void AveaBulb::onConnectionStatusChanged() void AveaBulb::serviceStateChanged(const QLowEnergyService::ServiceState &state) { - switch (state) { - case QLowEnergyService::ServiceDiscovered: - m_colorCharacteristic = m_colorService->characteristic(m_colorCharacteristicUuid); + QLowEnergyService *service =static_cast(sender()); - if (!m_colorCharacteristic.isValid()) { - qWarning() << "ERROR: color characteristc not found for device " << name() << address().toString(); - return; + switch (state) { + case QLowEnergyService::DiscoveringServices: + if (service->serviceUuid() == m_colorService->serviceUuid()) { + qDebug() << "start discovering color service..."; + } else if (service->serviceUuid() == m_imageService->serviceUuid()) { + qDebug() << "start discovering image service..."; + } + break; + case QLowEnergyService::ServiceDiscovered: + // check which service is discovered + if (service->serviceUuid() == m_colorService->serviceUuid()) { + qDebug() << "...color service discovered."; + + m_colorCharacteristic = m_colorService->characteristic(m_colorCharacteristicUuid); + + if (!m_colorCharacteristic.isValid()) { + qWarning() << "ERROR: color characteristc not found for device " << name() << address().toString(); + return; + } + + m_imageService->discoverDetails(); + } + if (service->serviceUuid() == m_imageService->serviceUuid()) { + qDebug() << "...image service discovered."; + + m_imageCharacteristic = m_imageService->characteristic(m_imageCharacteristicUuid); + + if (!m_imageCharacteristic.isValid()) { + qWarning() << "ERROR: image characteristc not found for device " << name() << address().toString(); + return; + } + } + + if (m_colorService->state() == QLowEnergyService::ServiceDiscovered && m_imageService->state() == QLowEnergyService::ServiceDiscovered) { + m_isAvailable = true; + emit availableChanged(); } - m_isAvailable = true; - emit availableChanged(); break; default: break; @@ -83,16 +135,43 @@ void AveaBulb::serviceCharacteristicChanged(const QLowEnergyCharacteristic &char void AveaBulb::confirmedCharacteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value) { if (characteristic.handle() == m_colorCharacteristic.handle()) { + qDebug() << "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()) { + qDebug() << "image char written successfully" << value.toHex(); } + +} + +void AveaBulb::confirmedDescriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value) +{ + qDebug() << "descriptor:" << descriptor.name() << "value:" << value.toHex() << "written successfully"; } void AveaBulb::serviceError(const QLowEnergyService::ServiceError &error) { - qWarning() << "ERROR: color service of " << name() << address().toString() << ":" << 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; + } + + qWarning() << "ERROR: color service of " << name() << address().toString() << ":" << errorString; } bool AveaBulb::enableNotification() @@ -101,8 +180,7 @@ bool AveaBulb::enableNotification() return false; qDebug() << "enable notify"; - QByteArray value = "0100"; - m_colorService->writeCharacteristic(m_colorCharacteristic, value, QLowEnergyService::WriteWithResponse); + m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex("0100"), QLowEnergyService::WriteWithResponse); return true; } @@ -112,10 +190,7 @@ bool AveaBulb::testMethod() if (!isAvailable()) return false; - QByteArray value = "34"; - qDebug() << "test" << value; - m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); - + setZauberwald(); return true; } @@ -144,3 +219,44 @@ bool AveaBulb::setWhite(ActionId actionId) return true; } + +bool AveaBulb::setZauberwald() +{ + if (!isAvailable()) + return false; + + m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex("340040143058220010"), QLowEnergyService::WriteWithResponse); + + QByteArray value = "1500cd0110cd0020cd0030cd2850cd5842cd14608d0a0ecd04708216c200a04d"; + m_imageService->writeCharacteristic(m_imageCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); + + value = "1600cd0210cd1280a1646301cd14608d080e" + "cd9041f190017402b564f200608d0a7d0ecd" + "6851b1c87402b564f200608d0a7d0ecdff47" + "cd6450cdb470823c44028564c200604d8d0a" + "0ecd17a0"; + m_imageService->writeCharacteristic(m_imageCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); + + value = "1700cd0310cd1280a1646301cde041cd2850" + "b1f07402b564f200608d0a7d0ecd04708216" + "c200a04d"; + m_imageService->writeCharacteristic(m_imageCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); + + value = "1800cd0410cd1280a1646301cdb841cdb470" + "823c7402b564c200604d8d0a0ecd0e41cd28" + "50b1c87402b564f200608d0a7d0ecd6440f1" + "90017402b564f200608d0a7d0e8d0a0ecd04" + "708216c200a04d"; + m_imageService->writeCharacteristic(m_imageCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); + + value = "1900cd0510cd1280a1646301cd6841cdb470" + "823cc200604d8d0a0ecda050f12c017402b5" + "64f200608d0a7d0ecdf040cd2850f1680174" + "02b564f200608d0a7d0ecdcc41b1c87402b5" + "64f200608d0a7d0ecd04708216c200a04d"; + m_imageService->writeCharacteristic(m_imageCharacteristic, QByteArray::fromHex(value), QLowEnergyService::WriteWithResponse); + + m_colorService->writeCharacteristic(m_colorCharacteristic, QByteArray::fromHex("2a15"), QLowEnergyService::WriteWithResponse); + + return true; +} diff --git a/plugins/deviceplugins/elgato/aveabulb.h b/plugins/deviceplugins/elgato/aveabulb.h index f80da713..596af3f1 100644 --- a/plugins/deviceplugins/elgato/aveabulb.h +++ b/plugins/deviceplugins/elgato/aveabulb.h @@ -21,6 +21,12 @@ private: QBluetoothUuid m_colorSeviceUuid; QLowEnergyService *m_colorService; + QBluetoothUuid m_imageSeviceUuid; + QLowEnergyService *m_imageService; + + QBluetoothUuid m_imageCharacteristicUuid; + QLowEnergyCharacteristic m_imageCharacteristic; + QBluetoothUuid m_colorCharacteristicUuid; QLowEnergyCharacteristic m_colorCharacteristic; @@ -36,16 +42,17 @@ private slots: 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); - bool enableNotification(); - bool testMethod(); public slots: + bool enableNotification(); + bool testMethod(); // actions bool actionPowerOff(ActionId actionId); bool setWhite(ActionId actionId); - + bool setZauberwald(); }; #endif // AVEABULB_H diff --git a/plugins/deviceplugins/elgato/devicepluginelgato.cpp b/plugins/deviceplugins/elgato/devicepluginelgato.cpp index d0a137e2..0e5d83e8 100644 --- a/plugins/deviceplugins/elgato/devicepluginelgato.cpp +++ b/plugins/deviceplugins/elgato/devicepluginelgato.cpp @@ -450,6 +450,12 @@ DeviceManager::DeviceError DevicePluginElgato::executeAction(Device *device, con if (device->deviceClassId() == aveaDeviceClassId) { AveaBulb *bulb = m_bulbs.key(device); + // reconnect action does not need available true + if (action.actionTypeId() == reconnectActionTypeId) { + bulb->reconnectDevice(); + return DeviceManager::DeviceErrorNoError; + } + // check available if (!bulb->isAvailable()) return DeviceManager::DeviceErrorHardwareNotAvailable; @@ -458,9 +464,10 @@ DeviceManager::DeviceError DevicePluginElgato::executeAction(Device *device, con bulb->actionPowerOff(action.id()); return DeviceManager::DeviceErrorAsync; } else if (action.actionTypeId() == whiteActionTypeId) { - bulb->setWhite(action.id()); + bulb->testMethod(); return DeviceManager::DeviceErrorAsync; } + return DeviceManager::DeviceErrorActionTypeNotFound; } return DeviceManager::DeviceErrorDeviceClassNotFound; @@ -511,6 +518,10 @@ void DevicePluginElgato::bulbAvailableChanged() AveaBulb *bulb =static_cast(sender()); Device *device = m_bulbs.value(bulb); device->setStateValue(availableStateTypeId, bulb->isAvailable()); + + if (bulb->isAvailable()) { + bulb->testMethod(); + } } void DevicePluginElgato::actionFinished(const ActionId actionId, const bool &success) diff --git a/plugins/deviceplugins/elgato/elgato.pro b/plugins/deviceplugins/elgato/elgato.pro index f56c92e4..139fb2af 100644 --- a/plugins/deviceplugins/elgato/elgato.pro +++ b/plugins/deviceplugins/elgato/elgato.pro @@ -2,15 +2,15 @@ include(../../plugins.pri) TARGET = $$qtLibraryTarget(guh_devicepluginelgato) -QT+= bluetooth - SOURCES += \ devicepluginelgato.cpp \ - aveabulb.cpp + aveabulb.cpp \ + imagefairywoods.cpp HEADERS += \ devicepluginelgato.h \ - aveabulb.h + aveabulb.h \ + imagefairywoods.h diff --git a/plugins/deviceplugins/elgato/imagefairywoods.cpp b/plugins/deviceplugins/elgato/imagefairywoods.cpp new file mode 100644 index 00000000..bb583232 --- /dev/null +++ b/plugins/deviceplugins/elgato/imagefairywoods.cpp @@ -0,0 +1,6 @@ +#include "imagefairywoods.h" + +ImageFairyWoods::ImageFairyWoods(QObject *parent) : + QObject(parent) +{ +} diff --git a/plugins/deviceplugins/elgato/imagefairywoods.h b/plugins/deviceplugins/elgato/imagefairywoods.h new file mode 100644 index 00000000..d3a3fb7c --- /dev/null +++ b/plugins/deviceplugins/elgato/imagefairywoods.h @@ -0,0 +1,18 @@ +#ifndef IMAGEFAIRYWOODS_H +#define IMAGEFAIRYWOODS_H + +#include + +class ImageFairyWoods : public QObject +{ + Q_OBJECT +public: + explicit ImageFairyWoods(QObject *parent = 0); + +signals: + +public slots: + +}; + +#endif // IMAGEFAIRYWOODS_H