Migrate senic plugin

master
Simon Stürz 2018-01-12 12:46:23 +01:00 committed by Michael Zanetti
parent 413cd748f4
commit cd2289563f
7 changed files with 351 additions and 349 deletions

17
debian/control vendored
View File

@ -446,6 +446,22 @@ Description: guh.io plugin for elgato
This package will install the guh.io plugin for elgato
Package: guh-plugin-senic
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
guh-plugins-translations,
Description: guh.io plugin for senic
The guh daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and
allows them to interact.
With the powerful rule engine you are able to connect any device available
in the system and create individual scenes and behaviors for your environment.
.
This package will install the guh.io plugin for senic
Package: guh-plugins-translations
Section: misc
Architecture: all
@ -479,6 +495,7 @@ Depends: guh-plugin-awattar,
guh-plugin-wakeonlan,
guh-plugin-wemo,
guh-plugin-elgato,
guh-plugin-senic
Description: Plugins for guh IoT server - the default plugin collection
The guh daemon is a plugin based IoT (Internet of Things) server. The
server works like a translator for devices, things and services and

View File

@ -21,7 +21,7 @@ PLUGIN_DIRS = \
tcpcommander \
kodi \
elgato \
#senic \
senic \
awattar \
netatmo \
plantcare \

View File

@ -37,18 +37,23 @@
\quotefile plugins/deviceplugins/senic/devicepluginsenic.json
*/
#ifdef BLUETOOTH_LE
#include "devicepluginsenic.h"
#include "plugin/device.h"
#include "devicemanager.h"
#include "plugininfo.h"
#include "hardware/bluetoothlowenergy/bluetoothlowenergymanager.h"
DevicePluginSenic::DevicePluginSenic()
{
}
void DevicePluginSenic::init()
{
m_reconnectTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_reconnectTimer, &PluginTimer::timeout, this, &DevicePluginSenic::onReconnectTimeout);
}
DeviceManager::DeviceError DevicePluginSenic::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
Q_UNUSED(params)
@ -56,55 +61,46 @@ DeviceManager::DeviceError DevicePluginSenic::discoverDevices(const DeviceClassI
if (deviceClassId != nuimoDeviceClassId)
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, &DevicePluginSenic::onBluetoothDiscoveryFinished);
return DeviceManager::DeviceErrorAsync;
}
DeviceManager::DeviceSetupStatus DevicePluginSenic::setupDevice(Device *device)
{
qCDebug(dcSenic()) << "Setup device" << device->name() << device->params();
QString name = device->paramValue(nameParamTypeId).toString();
QBluetoothAddress address = QBluetoothAddress(device->paramValue(macParamTypeId).toString());
QBluetoothDeviceInfo deviceInfo = QBluetoothDeviceInfo(address, name, 0);
Nuimo *nuimo = new Nuimo(deviceInfo, QLowEnergyController::RandomAddress, this);
connect(nuimo, &Nuimo::availableChanged, this, &DevicePluginSenic::connectionAvailableChanged);
connect(nuimo, &Nuimo::batteryValueChaged, this, &DevicePluginSenic::onBatteryValueChanged);
BluetoothLowEnergyDevice *bluetoothDevice = hardwareManager()->bluetoothLowEnergyManager()->registerDevice(deviceInfo, QLowEnergyController::RandomAddress);
Nuimo *nuimo = new Nuimo(device, bluetoothDevice, this);
connect(nuimo, &Nuimo::buttonPressed, this, &DevicePluginSenic::onButtonPressed);
connect(nuimo, &Nuimo::buttonReleased, this, &DevicePluginSenic::onButtonReleased);
connect(nuimo, &Nuimo::swipeDetected, this, &DevicePluginSenic::onSwipeDetected);
connect(nuimo, &Nuimo::rotationValueChanged, this, &DevicePluginSenic::onRotationValueChanged);
m_nuimos.insert(nuimo, device);
nuimo->connectDevice();
nuimo->bluetoothDevice()->connectDevice();
return DeviceManager::DeviceSetupStatusSuccess;
}
DeviceManager::HardwareResources DevicePluginSenic::requiredHardware() const
{
return DeviceManager::HardwareResourceBluetoothLE;
}
DeviceManager::DeviceError DevicePluginSenic::executeAction(Device *device, const Action &action)
{
QPointer<Nuimo> nuimo = m_nuimos.key(device);
if (nuimo.isNull())
return DeviceManager::DeviceErrorHardwareFailure;
// reconnect action does not need available true
if (action.actionTypeId() == connectActionTypeId) {
nuimo->reconnectDevice();
return DeviceManager::DeviceErrorNoError;
}
if (action.actionTypeId() == disconnectActionTypeId) {
nuimo->disconnectDevice();
return DeviceManager::DeviceErrorNoError;
}
if (action.actionTypeId() == showLogoActionTypeId) {
if (action.param(logoParamTypeId).value().toString() == "Guh")
@ -122,25 +118,6 @@ DeviceManager::DeviceError DevicePluginSenic::executeAction(Device *device, cons
return DeviceManager::DeviceErrorActionTypeNotFound;
}
void DevicePluginSenic::bluetoothDiscoveryFinished(const QList<QBluetoothDeviceInfo> &deviceInfos)
{
QList<DeviceDescriptor> deviceDescriptors;
foreach (QBluetoothDeviceInfo deviceInfo, deviceInfos) {
if (deviceInfo.name().contains("Nuimo")) {
if (!verifyExistingDevices(deviceInfo)) {
DeviceDescriptor descriptor(nuimoDeviceClassId, "Nuimo", deviceInfo.address().toString());
ParamList params;
params.append(Param(nameParamTypeId, deviceInfo.name()));
params.append(Param(macParamTypeId, deviceInfo.address().toString()));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
}
}
emit devicesDiscovered(nuimoDeviceClassId, deviceDescriptors);
}
void DevicePluginSenic::deviceRemoved(Device *device)
{
if (!m_nuimos.values().contains(device))
@ -161,20 +138,45 @@ bool DevicePluginSenic::verifyExistingDevices(const QBluetoothDeviceInfo &device
return false;
}
void DevicePluginSenic::connectionAvailableChanged()
void DevicePluginSenic::onReconnectTimeout()
{
Nuimo *nuimo = static_cast<Nuimo *>(sender());
Device *device = m_nuimos.value(nuimo);
device->setStateValue(availableStateTypeId, nuimo->isAvailable());
foreach (Nuimo *nuimo, m_nuimos.keys()) {
if (!nuimo->bluetoothDevice()->connected()) {
nuimo->bluetoothDevice()->connectDevice();
}
}
}
void DevicePluginSenic::onBatteryValueChanged(const uint &percentage)
void DevicePluginSenic::onBluetoothDiscoveryFinished()
{
Nuimo *nuimo = static_cast<Nuimo *>(sender());
Device *device = m_nuimos.value(nuimo);
device->setStateValue(batteryStateTypeId, percentage);
BluetoothDiscoveryReply *reply = static_cast<BluetoothDiscoveryReply *>(sender());
if (reply->error() != BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorNoError) {
qCWarning(dcSenic()) << "Bluetooth discovery error:" << reply->error();
reply->deleteLater();
emit devicesDiscovered(nuimoDeviceClassId, QList<DeviceDescriptor>());
return;
}
QList<DeviceDescriptor> deviceDescriptors;
foreach (const QBluetoothDeviceInfo &deviceInfo, reply->discoveredDevices()) {
if (deviceInfo.name().contains("Nuimo")) {
if (!verifyExistingDevices(deviceInfo)) {
DeviceDescriptor descriptor(nuimoDeviceClassId, "Nuimo", deviceInfo.address().toString());
ParamList params;
params.append(Param(nameParamTypeId, deviceInfo.name()));
params.append(Param(macParamTypeId, deviceInfo.address().toString()));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
}
}
reply->deleteLater();
emit devicesDiscovered(nuimoDeviceClassId, deviceDescriptors);
}
void DevicePluginSenic::onButtonPressed()
{
Nuimo *nuimo = static_cast<Nuimo *>(sender());
@ -218,6 +220,3 @@ void DevicePluginSenic::onRotationValueChanged(const uint &value)
}
#endif // BLUETOOTH_LE

View File

@ -23,10 +23,9 @@
#ifndef DEVICEPLUGINELGATO_H
#define DEVICEPLUGINELGATO_H
#ifdef BLUETOOTH_LE
#include "plugintimer.h"
#include "plugin/deviceplugin.h"
#include "bluetooth/bluetoothlowenergydevice.h"
#include "hardware/bluetoothlowenergy/bluetoothlowenergydevice.h"
#include "nuimo.h"
@ -40,21 +39,23 @@ class DevicePluginSenic : public DevicePlugin
public:
explicit DevicePluginSenic();
void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) 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<QBluetoothDeviceInfo> &deviceInfos);
void deviceRemoved(Device *device) override;
private:
QHash<Nuimo *, Device *> m_nuimos;
PluginTimer *m_reconnectTimer = nullptr;
bool verifyExistingDevices(const QBluetoothDeviceInfo &deviceInfo);
private slots:
void connectionAvailableChanged();
void onBatteryValueChanged(const uint &percentage);
void onReconnectTimeout();
void onBluetoothDiscoveryFinished();
void onButtonPressed();
void onButtonReleased();
void onSwipeDetected(const Nuimo::SwipeDirection &direction);
@ -62,6 +63,4 @@ private slots:
};
#endif // BLUETOOTH_LE
#endif // DEVICEPLUGINELGATO_H

View File

@ -37,12 +37,36 @@
"stateTypes": [
{
"id": "5286976a-f5dc-4662-872a-438ac5d491cb",
"idName": "available",
"name": "available",
"eventTypeName": "available changed",
"idName": "connected",
"name": "Connected",
"eventTypeName": "Connected changed",
"type": "bool",
"defaultValue": false
},
{
"id": "5c400da4-a14e-4e0a-be9f-c82ffe7e1972",
"idName": "hardwareRevision",
"name": "Hardware revision",
"eventTypeName": "Hardware revision changed",
"type": "QString",
"defaultValue": "-"
},
{
"id": "edcf76c6-9fed-4c26-9853-c284cf887adb",
"idName": "firmwareRevision",
"name": "Firmware revision",
"eventTypeName": "Firmware revision changed",
"type": "QString",
"defaultValue": "-"
},
{
"id": "be42cbd3-12e9-44ec-8f9d-141e10d9573a",
"idName": "softwareRevision",
"name": "Software revision",
"eventTypeName": "Software revision changed",
"type": "QString",
"defaultValue": "-"
},
{
"id": "b5ee2465-7fa1-450b-8073-f115537d3409",
"idName": "battery",
@ -67,16 +91,6 @@
}
],
"actionTypes": [
{
"id": "bb1c46fe-5dfb-4fa3-ad89-0ba576ac780e",
"idName": "connect",
"name": "connect"
},
{
"id": "11bf3143-34f8-42ab-9750-073040c1a7fc",
"idName": "disconnect",
"name": "disconnect"
},
{
"id": "d44ca5b7-f8d6-4413-9d2e-cef89282c039",
"idName": "showLogo",

View File

@ -20,29 +20,38 @@
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifdef BLUETOOTH_LE
#include "nuimo.h"
#include "extern-plugininfo.h"
#include <QBitArray>
#include <QtEndian>
Nuimo::Nuimo(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType, QObject *parent) :
BluetoothLowEnergyDevice(deviceInfo, addressType, parent),
m_deviceInfoService(NULL),
m_batteryService(NULL),
m_inputService(NULL),
m_ledMatrixService(NULL),
m_isAvailable(false)
static QBluetoothUuid ledMatrinxServiceUuid = QBluetoothUuid(QUuid("f29b1523-cb19-40f3-be5c-7241ecb82fd1"));
static QBluetoothUuid ledMatrixCharacteristicUuid = QBluetoothUuid(QUuid("f29b1524-cb19-40f3-be5c-7241ecb82fd1"));
static QBluetoothUuid inputServiceUuid = QBluetoothUuid(QUuid("f29b1525-cb19-40f3-be5c-7241ecb82fd2"));
static QBluetoothUuid inputSwipeCharacteristicUuid = QBluetoothUuid(QUuid("f29b1527-cb19-40f3-be5c-7241ecb82fd2"));
static QBluetoothUuid inputRotationCharacteristicUuid = QBluetoothUuid(QUuid("f29b1528-cb19-40f3-be5c-7241ecb82fd2"));
static QBluetoothUuid inputButtonCharacteristicUuid = QBluetoothUuid(QUuid("f29b1529-cb19-40f3-be5c-7241ecb82fd2"));
Nuimo::Nuimo(Device *device, BluetoothLowEnergyDevice *bluetoothDevice, QObject *parent) :
QObject(parent),
m_device(device),
m_bluetoothDevice(bluetoothDevice)
{
connect(this, SIGNAL(connectionStatusChanged()), this,SLOT(onConnectionStatusChanged()));
connect(this, SIGNAL(servicesDiscoveryFinished()), this, SLOT(serviceScanFinished()));
connect(m_bluetoothDevice, &BluetoothLowEnergyDevice::connectedChanged, this, &Nuimo::onConnectedChanged);
connect(m_bluetoothDevice, &BluetoothLowEnergyDevice::servicesDiscoveryFinished, this, &Nuimo::onServiceDiscoveryFinished);
}
bool Nuimo::isAvailable()
Device *Nuimo::device()
{
return m_isAvailable;
return m_device;
}
BluetoothLowEnergyDevice *Nuimo::bluetoothDevice()
{
return m_bluetoothDevice;
}
void Nuimo::showGuhLogo()
@ -93,19 +102,11 @@ void Nuimo::showArrowDown()
showMatrix(matrix, 3);
}
void Nuimo::registerService(QLowEnergyService *service)
{
connect(service, SIGNAL(stateChanged(QLowEnergyService::ServiceState)), this, SLOT(serviceStateChanged(QLowEnergyService::ServiceState)));
connect(service, SIGNAL(characteristicChanged(QLowEnergyCharacteristic, QByteArray)), this, SLOT(serviceCharacteristicChanged(QLowEnergyCharacteristic, QByteArray)));
connect(service, SIGNAL(characteristicWritten(QLowEnergyCharacteristic, QByteArray)), this, SLOT(confirmedCharacteristicWritten(QLowEnergyCharacteristic, QByteArray)));
connect(service, SIGNAL(descriptorWritten(QLowEnergyDescriptor, QByteArray)), this, SLOT(confirmedDescriptorWritten(QLowEnergyDescriptor, QByteArray)));
connect(service, SIGNAL(error(QLowEnergyService::ServiceError)), this, SLOT(serviceError(QLowEnergyService::ServiceError)));
service->discoverDetails();
}
void Nuimo::showMatrix(const QByteArray &matrix, const int &seconds)
{
if (!m_ledMatrixService)
return;
QBitArray bits;
bits.resize(81);
for (int i = 0; i < matrix.size(); i++) {
@ -127,225 +128,223 @@ void Nuimo::showMatrix(const QByteArray &matrix, const int &seconds)
m_ledMatrixService->writeCharacteristic(m_ledMatrixCharacteristic, bytes);
}
void Nuimo::serviceScanFinished()
void Nuimo::printService(QLowEnergyService *service)
{
QBluetoothUuid deviceInfoUuid(QUuid("0000180A-0000-1000-8000-00805F9B34FB"));
QBluetoothUuid batteryUuid(QUuid("0000180F-0000-1000-8000-00805F9B34FB"));
QBluetoothUuid inputUuid(QUuid("F29B1525-CB19-40F3-BE5C-7241ECB82FD2"));
QBluetoothUuid ledMatrixUuid(QUuid("F29B1523-CB19-40F3-BE5C-7241ECB82FD1"));
foreach (const QLowEnergyCharacteristic &characteristic, service->characteristics()) {
qCDebug(dcSenic()) << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value();
foreach (const QLowEnergyDescriptor &desciptor, characteristic.descriptors()) {
qCDebug(dcSenic()) << " -->" << desciptor.name() << desciptor.uuid().toString() << desciptor.value();
}
}
}
void Nuimo::setBatteryValue(const QByteArray &data)
{
int batteryPercentage = data.toHex().toUInt(0, 16);
qCDebug(dcSenic()) << "Battery:" << batteryPercentage << "%";
device()->setStateValue(batteryStateTypeId, batteryPercentage);
}
void Nuimo::onConnectedChanged(const bool &connected)
{
qCDebug(dcSenic()) << m_bluetoothDevice->name() << m_bluetoothDevice->address().toString() << (connected ? "connected" : "disconnected");
m_device->setStateValue(connectedStateTypeId, connected);
if (!connected) {
// Clean up services
m_deviceInfoService->deleteLater();
m_batteryService->deleteLater();
m_ledMatrixService->deleteLater();
m_inputService->deleteLater();
m_deviceInfoService = nullptr;
m_batteryService = nullptr;
m_ledMatrixService = nullptr;
m_inputService = nullptr;
}
}
void Nuimo::onServiceDiscoveryFinished()
{
qCDebug(dcSenic()) << "Service scan finised";
if (!controller()->services().contains(deviceInfoUuid)) {
qCWarning(dcSenic()) << "Device Information service not found for device" << name() << address().toString();
if (!m_bluetoothDevice->serviceUuids().contains(QBluetoothUuid::DeviceInformation)) {
qCWarning(dcSenic()) << "Device Information service not found for device" << bluetoothDevice()->name() << bluetoothDevice()->address().toString();
return;
}
if (!controller()->services().contains(batteryUuid)) {
qCWarning(dcSenic()) << "Battery service not found for device" << name() << address().toString();
if (!m_bluetoothDevice->serviceUuids().contains(QBluetoothUuid::BatteryService)) {
qCWarning(dcSenic()) << "Battery service not found for device" << bluetoothDevice()->name() << bluetoothDevice()->address().toString();
return;
}
if (!controller()->services().contains(ledMatrixUuid)) {
qCWarning(dcSenic()) << "Led matrix service not found for device" << name() << address().toString();
if (!m_bluetoothDevice->serviceUuids().contains(ledMatrinxServiceUuid)) {
qCWarning(dcSenic()) << "Led matrix service not found for device" << bluetoothDevice()->name() << bluetoothDevice()->address().toString();
return;
}
if (!controller()->services().contains(inputUuid)) {
qCWarning(dcSenic()) << "Input service not found for device" << name() << address().toString();
if (!m_bluetoothDevice->serviceUuids().contains(inputServiceUuid)) {
qCWarning(dcSenic()) << "Input service not found for device" << bluetoothDevice()->name() << bluetoothDevice()->address().toString();
return;
}
m_isAvailable = true;
emit availableChanged();
// Device information
m_deviceInfoService = controller()->createServiceObject(deviceInfoUuid, this);
// Device info service
if (!m_deviceInfoService) {
qCWarning(dcSenic()) << "Could not create device information service for device" << name() << address().toString();
m_deviceInfoService = m_bluetoothDevice->controller()->createServiceObject(QBluetoothUuid::DeviceInformation, this);
if (!m_deviceInfoService) {
qCWarning(dcSenic()) << "Could not create device info service.";
return;
}
connect(m_deviceInfoService, &QLowEnergyService::stateChanged, this, &Nuimo::onDeviceInfoServiceStateChanged);
if (m_deviceInfoService->state() == QLowEnergyService::DiscoveryRequired) {
m_deviceInfoService->discoverDetails();
}
}
// Battery service
m_batteryService = controller()->createServiceObject(batteryUuid, this);
if (!m_batteryService) {
qCWarning(dcSenic()) << "Could not create battery service for device" << name() << address().toString();
m_batteryService = m_bluetoothDevice->controller()->createServiceObject(QBluetoothUuid::BatteryService, this);
if (!m_batteryService) {
qCWarning(dcSenic()) << "Could not create battery service.";
return;
}
connect(m_batteryService, &QLowEnergyService::stateChanged, this, &Nuimo::onBatteryServiceStateChanged);
connect(m_batteryService, &QLowEnergyService::characteristicChanged, this, &Nuimo::onBatteryCharacteristicChanged);
if (m_batteryService->state() == QLowEnergyService::DiscoveryRequired) {
m_batteryService->discoverDetails();
}
}
// Input service
m_inputService = controller()->createServiceObject(inputUuid, this);
if (!m_inputService) {
qCWarning(dcSenic()) << "Could not create input service for device" << name() << address().toString();
m_inputService = m_bluetoothDevice->controller()->createServiceObject(inputServiceUuid, this);
if (!m_inputService) {
qCWarning(dcSenic()) << "Could not create input service.";
return;
}
// Led Matrix
m_ledMatrixService = controller()->createServiceObject(ledMatrixUuid, this);
connect(m_inputService, &QLowEnergyService::stateChanged, this, &Nuimo::onInputServiceStateChanged);
connect(m_inputService, &QLowEnergyService::characteristicChanged, this, &Nuimo::onInputCharacteristicChanged);
if (m_inputService->state() == QLowEnergyService::DiscoveryRequired) {
m_inputService->discoverDetails();
}
}
// Input service
if (!m_ledMatrixService) {
qCWarning(dcSenic()) << "Could not create led matrix service for device" << name() << address().toString();
m_ledMatrixService = m_bluetoothDevice->controller()->createServiceObject(ledMatrinxServiceUuid, this);
if (!m_ledMatrixService) {
qCWarning(dcSenic()) << "Could not create led matrix service.";
return;
}
registerService(m_deviceInfoService);
registerService(m_batteryService);
registerService(m_inputService);
registerService(m_ledMatrixService);
connect(m_ledMatrixService, &QLowEnergyService::stateChanged, this, &Nuimo::onLedMatrixServiceStateChanged);
if (m_ledMatrixService->state() == QLowEnergyService::DiscoveryRequired) {
m_ledMatrixService->discoverDetails();
}
}
}
void Nuimo::onConnectionStatusChanged()
void Nuimo::onDeviceInfoServiceStateChanged(const QLowEnergyService::ServiceState &state)
{
if (!isConnected()) {
// delete the services, they need to be recreated and
// rediscovered once the device will be reconnected
if (m_deviceInfoService) {
delete m_deviceInfoService;
m_deviceInfoService = 0;
}
if (m_batteryService) {
delete m_batteryService;
m_batteryService = 0;
}
if (m_inputService) {
delete m_inputService;
m_inputService = 0;
}
if (m_ledMatrixService) {
delete m_ledMatrixService;
m_ledMatrixService = 0;
}
m_isAvailable = false;
emit availableChanged();
}
}
void Nuimo::serviceStateChanged(const QLowEnergyService::ServiceState &state)
{
QLowEnergyService *service =static_cast<QLowEnergyService *>(sender());
switch (state) {
case QLowEnergyService::DiscoveringServices:
if (service == m_batteryService)
qCDebug(dcSenic()) << "Start discovering battery service...";
if (service == m_deviceInfoService)
qCDebug(dcSenic()) << "Start discovering device information service...";
if (service == m_inputService)
qCDebug(dcSenic()) << "Start discovering input service...";
if (service == m_ledMatrixService)
qCDebug(dcSenic()) << "Start discovering led matrix service...";
break;
case QLowEnergyService::ServiceDiscovered:
// Device information
if (service == m_deviceInfoService) {
qCDebug(dcSenic()) << "Device information service discovered";
m_deviceInfoCharacteristic = m_deviceInfoService->characteristic(QBluetoothUuid(QUuid("00002A29-0000-1000-8000-00805F9B34FB")));
if (!m_deviceInfoCharacteristic.isValid()) {
qCWarning(dcSenic()) << "Device information characteristc not found for device " << name() << address().toString();
// Only continue if discovered
if (state != QLowEnergyService::ServiceDiscovered)
return;
}
qCDebug(dcSenic()) << "Device information:" << m_deviceInfoCharacteristic.value();
}
qCDebug(dcSenic()) << "Device info service discovered.";
// Battery
if (service == m_batteryService) {
qCDebug(dcSenic()) << "Battery service discovered";
m_batteryCharacteristic = m_batteryService->characteristic(QBluetoothUuid(QUuid("00002A19-0000-1000-8000-00805F9B34FB")));
printService(m_deviceInfoService);
device()->setStateValue(firmwareRevisionStateTypeId, QString::fromUtf8(m_deviceInfoService->characteristic(QBluetoothUuid::FirmwareRevisionString).value()));
device()->setStateValue(hardwareRevisionStateTypeId, QString::fromUtf8(m_deviceInfoService->characteristic(QBluetoothUuid::HardwareRevisionString).value()));
device()->setStateValue(softwareRevisionStateTypeId, QString::fromUtf8(m_deviceInfoService->characteristic(QBluetoothUuid::SoftwareRevisionString).value()));
}
void Nuimo::onBatteryServiceStateChanged(const QLowEnergyService::ServiceState &state)
{
// Only continue if discovered
if (state != QLowEnergyService::ServiceDiscovered)
return;
qCDebug(dcSenic()) << "Battery service discovered.";
printService(m_batteryService);
m_batteryCharacteristic = m_batteryService->characteristic(QBluetoothUuid::BatteryLevel);
if (!m_batteryCharacteristic.isValid()) {
qCWarning(dcSenic()) << "Battery characteristc not found for device " << name() << address().toString();
qCWarning(dcSenic()) << "Battery characteristc not found for device " << bluetoothDevice()->name() << bluetoothDevice()->address().toString();
return;
}
int batteryPercentage = m_batteryCharacteristic.value().toHex().toUInt(0, 16);
qCDebug(dcSenic()) << "Battery:" << batteryPercentage << "%";
// Enable notifications
QLowEnergyDescriptor notificationDescriptor = m_batteryCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_batteryService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
// Enable notification
foreach (const QLowEnergyDescriptor &descriptor, m_batteryCharacteristic.descriptors()) {
qCDebug(dcSenic()) << descriptor.name() << descriptor.uuid().toString();
m_batteryService->writeDescriptor(descriptor, QByteArray::fromHex("0100"));
}
emit batteryValueChaged(batteryPercentage);
}
// Input
if (service == m_inputService) {
qCDebug(dcSenic()) << "Input service discovered";
// Button
m_inputButtonCharacteristic = m_inputService->characteristic(QBluetoothUuid(QUuid("F29B1529-CB19-40F3-BE5C-7241ECB82FD2")));
if (!m_inputButtonCharacteristic.isValid()) {
qCWarning(dcSenic()) << "Button characteristc not valid for device " << name() << address().toString();
return;
}
foreach (const QLowEnergyDescriptor &descriptor, m_inputButtonCharacteristic.descriptors()) {
qCDebug(dcSenic()) << descriptor.name() << descriptor.uuid().toString();
m_inputService->writeDescriptor(descriptor, QByteArray::fromHex("0100"));
}
// Swipe
m_inputSwipeCharacteristic = m_inputService->characteristic(QBluetoothUuid(QUuid("F29B1527-CB19-40F3-BE5C-7241ECB82FD2")));
if (!m_inputSwipeCharacteristic.isValid()) {
qCWarning(dcSenic()) << "Swipe characteristc not valid for device " << name() << address().toString();
return;
}
foreach (const QLowEnergyDescriptor &descriptor, m_inputSwipeCharacteristic.descriptors()) {
qCDebug(dcSenic()) << descriptor.name() << descriptor.uuid().toString();
m_inputService->writeDescriptor(descriptor, QByteArray::fromHex("0100"));
}
// Swipe
m_inputRotationCharacteristic = m_inputService->characteristic(QBluetoothUuid(QUuid("F29B1528-CB19-40F3-BE5C-7241ECB82FD2")));
if (!m_inputRotationCharacteristic.isValid()) {
qCWarning(dcSenic()) << "Rotation characteristc not valid for device " << name() << address().toString();
return;
}
foreach (const QLowEnergyDescriptor &descriptor, m_inputRotationCharacteristic.descriptors()) {
qCDebug(dcSenic()) << descriptor.name() << descriptor.uuid().toString();
m_inputService->writeDescriptor(descriptor, QByteArray::fromHex("0100"));
}
}
// Led Matrix
if (service == m_ledMatrixService) {
qCDebug(dcSenic()) << "Led matrix service discovered";
m_ledMatrixCharacteristic = m_ledMatrixService->characteristic(QBluetoothUuid(QUuid("F29B1524-CB19-40F3-BE5C-7241ECB82FD1")));
if (!m_ledMatrixCharacteristic.isValid()) {
qCWarning(dcSenic()) << "Led matrix characteristc not found for device " << name() << address().toString();
return;
}
showGuhLogo();
}
break;
default:
break;
}
setBatteryValue(m_batteryCharacteristic.value());
}
void Nuimo::serviceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
void Nuimo::onBatteryCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
if (characteristic.uuid() == m_batteryCharacteristic.uuid()) {
uint batteryValue = value.toHex().toUInt(0, 16);
qCDebug(dcSenic()) << "Battery:" << batteryValue;
emit batteryValueChaged(batteryValue);
setBatteryValue(value);
}
}
void Nuimo::onInputServiceStateChanged(const QLowEnergyService::ServiceState &state)
{
// Only continue if discovered
if (state != QLowEnergyService::ServiceDiscovered)
return;
qCDebug(dcSenic()) << "Input service discovered.";
printService(m_inputService);
// Button
m_inputButtonCharacteristic = m_inputService->characteristic(inputButtonCharacteristicUuid);
if (!m_inputButtonCharacteristic.isValid()) {
qCWarning(dcSenic()) << "Input button characteristc not found for device " << bluetoothDevice()->name() << bluetoothDevice()->address().toString();
return;
}
// Enable notifications
QLowEnergyDescriptor notificationDescriptor = m_inputButtonCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_inputService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
// Swipe
m_inputSwipeCharacteristic = m_inputService->characteristic(inputSwipeCharacteristicUuid);
if (!m_inputSwipeCharacteristic.isValid()) {
qCWarning(dcSenic()) << "Input swipe characteristc not found for device " << bluetoothDevice()->name() << bluetoothDevice()->address().toString();
return;
}
// Enable notifications
notificationDescriptor = m_inputSwipeCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_inputService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
// Rotation
m_inputRotationCharacteristic = m_inputService->characteristic(inputRotationCharacteristicUuid);
if (!m_inputRotationCharacteristic.isValid()) {
qCWarning(dcSenic()) << "Input rotation characteristc not found for device " << bluetoothDevice()->name() << bluetoothDevice()->address().toString();
return;
}
// Enable notifications
notificationDescriptor = m_inputRotationCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_inputService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
}
void Nuimo::onInputCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
if (characteristic.uuid() == m_inputButtonCharacteristic.uuid()) {
bool pressed = (bool)value.toHex().toUInt(0, 16);
qCDebug(dcSenic()) << "Button:" << (pressed ? "pressed": "released");
@ -397,57 +396,23 @@ void Nuimo::serviceCharacteristicChanged(const QLowEnergyCharacteristic &charact
return;
}
qCDebug(dcSenic()) << "Service characteristic changed" << characteristic.name() << value.toHex();
}
void Nuimo::confirmedCharacteristicWritten(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
void Nuimo::onLedMatrixServiceStateChanged(const QLowEnergyService::ServiceState &state)
{
qCDebug(dcSenic()) << characteristic.name() << value;
}
// Only continue if discovered
if (state != QLowEnergyService::ServiceDiscovered)
return;
void Nuimo::confirmedDescriptorWritten(const QLowEnergyDescriptor &descriptor, const QByteArray &value)
{
qCDebug(dcSenic()) << "Descriptor:" << descriptor.name() << "value:" << value.toHex() << "written successfully";
}
qCDebug(dcSenic()) << "Led matrix service discovered.";
void Nuimo::serviceError(const QLowEnergyService::ServiceError &error)
{
QString errorString;
switch (error) {
case QLowEnergyService::NoError:
errorString = "No error";
break;
case QLowEnergyService::OperationError:
errorString = "Operation error";
break;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
case QLowEnergyService::CharacteristicReadError:
errorString = "Characteristic read error";
break;
#endif
case QLowEnergyService::CharacteristicWriteError:
errorString = "Characteristic write error";
break;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
case QLowEnergyService::DescriptorReadError:
errorString = "Descriptor read error";
break;
#endif
case QLowEnergyService::DescriptorWriteError:
errorString = "Descriptor write error";
break;
#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0))
case QLowEnergyService::UnknownError:
errorString = "Unknown error";
break;
#endif
default:
errorString = "Unknown error";
break;
printService(m_ledMatrixService);
// Led matrix
m_ledMatrixCharacteristic = m_ledMatrixService->characteristic(ledMatrixCharacteristicUuid);
if (!m_ledMatrixCharacteristic.isValid()) {
qCWarning(dcSenic()) << "Led matrix characteristc not found for device " << bluetoothDevice()->name() << bluetoothDevice()->address().toString();
return;
}
qCWarning(dcSenic()) << "Service error of" << name() << address().toString() << ":" << errorString;
}
#endif // BLUETOOTH_LE

View File

@ -23,15 +23,14 @@
#ifndef NUIMO_H
#define NUIMO_H
#ifdef BLUETOOTH_LE
#include <QObject>
#include <QBluetoothUuid>
#include "typeutils.h"
#include "bluetooth/bluetoothlowenergydevice.h"
#include "plugin/device.h"
#include "hardware/bluetoothlowenergy/bluetoothlowenergydevice.h"
class Nuimo : public BluetoothLowEnergyDevice
class Nuimo : public QObject
{
Q_OBJECT
public:
@ -42,19 +41,23 @@ public:
SwipeDirectionDown
};
explicit Nuimo(const QBluetoothDeviceInfo &deviceInfo, const QLowEnergyController::RemoteAddressType &addressType, QObject *parent = 0);
explicit Nuimo(Device *device, BluetoothLowEnergyDevice *bluetoothDevice, QObject *parent = nullptr);
bool isAvailable();
Device *device();
BluetoothLowEnergyDevice *bluetoothDevice();
void showGuhLogo();
void showArrowUp();
void showArrowDown();
private:
QLowEnergyService *m_deviceInfoService;
QLowEnergyService *m_batteryService;
QLowEnergyService *m_inputService;
QLowEnergyService *m_ledMatrixService;
Device *m_device = nullptr;
BluetoothLowEnergyDevice *m_bluetoothDevice = nullptr;
QLowEnergyService *m_deviceInfoService = nullptr;
QLowEnergyService *m_batteryService = nullptr;
QLowEnergyService *m_inputService = nullptr;
QLowEnergyService *m_ledMatrixService = nullptr;
QLowEnergyCharacteristic m_deviceInfoCharacteristic;
QLowEnergyCharacteristic m_batteryCharacteristic;
@ -63,12 +66,15 @@ private:
QLowEnergyCharacteristic m_inputSwipeCharacteristic;
QLowEnergyCharacteristic m_inputRotationCharacteristic;
bool m_isAvailable;
uint m_rotationValue;
void registerService(QLowEnergyService *service);
void showMatrix(const QByteArray &matrix, const int &seconds);
void printService(QLowEnergyService *service);
// Set states
void setBatteryValue(const QByteArray &data);
signals:
void availableChanged();
void buttonPressed();
@ -78,17 +84,19 @@ signals:
void rotationValueChanged(const uint &value);
private slots:
void serviceScanFinished();
void onConnectionStatusChanged();
void onConnectedChanged(const bool &connected);
void onServiceDiscoveryFinished();
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 onDeviceInfoServiceStateChanged(const QLowEnergyService::ServiceState &state);
void onBatteryServiceStateChanged(const QLowEnergyService::ServiceState &state);
void onBatteryCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
void onInputServiceStateChanged(const QLowEnergyService::ServiceState &state);
void onInputCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
void onLedMatrixServiceStateChanged(const QLowEnergyService::ServiceState &state);
};
#endif // BLUETOOTH_LE
#endif // NUIMO_H