Merge remote-tracking branch 'origin/texas-instruments-sensortag'

This commit is contained in:
Jenkins 2018-03-14 19:59:38 +01:00
commit 0dde37ee41
11 changed files with 1906 additions and 243 deletions

View File

@ -1,6 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.io> *
* Copyright (C) 2015-2018 Simon Stuerz <simon.stuerz@guh.io> *
* Copyright (C) 2016 nicc *
* *
* This file is part of nymea. *
@ -52,17 +52,22 @@ DevicePluginMultiSensor::DevicePluginMultiSensor()
}
DevicePluginMultiSensor::~DevicePluginMultiSensor()
{
hardwareManager()->pluginTimerManager()->unregisterTimer(m_reconnectTimer);
}
void DevicePluginMultiSensor::init()
{
m_measureTimer = hardwareManager()->pluginTimerManager()->registerTimer(60);
connect(m_measureTimer, &PluginTimer::timeout, this, &DevicePluginMultiSensor::onPluginTimer);
m_reconnectTimer = hardwareManager()->pluginTimerManager()->registerTimer(10);
connect(m_reconnectTimer, &PluginTimer::timeout, this, &DevicePluginMultiSensor::onPluginTimer);
}
DeviceManager::DeviceError DevicePluginMultiSensor::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params)
{
Q_UNUSED(params)
if (deviceClassId != sensortagDeviceClassId)
if (deviceClassId != sensorTagDeviceClassId)
return DeviceManager::DeviceErrorDeviceClassNotFound;
if (!hardwareManager()->bluetoothLowEnergyManager()->available())
@ -80,26 +85,41 @@ DeviceManager::DeviceSetupStatus DevicePluginMultiSensor::setupDevice(Device *de
{
qCDebug(dcMultiSensor) << "Setting up Multi Sensor" << device->name() << device->params();
if (device->deviceClassId() == sensortagDeviceClassId) {
if (device->deviceClassId() == sensorTagDeviceClassId) {
QBluetoothAddress address = QBluetoothAddress(device->paramValue(sensortagMacParamTypeId).toString());
QString name = device->paramValue(sensortagNameParamTypeId).toString();
QBluetoothAddress address = QBluetoothAddress(device->paramValue(sensorTagMacParamTypeId).toString());
QString name = device->paramValue(sensorTagNameParamTypeId).toString();
QBluetoothDeviceInfo deviceInfo = QBluetoothDeviceInfo(address, name, 0);
BluetoothLowEnergyDevice *bluetoothDevice = hardwareManager()->bluetoothLowEnergyManager()->registerDevice(deviceInfo, QLowEnergyController::PublicAddress);
SensorTag *sensor = new SensorTag(device, bluetoothDevice, this);
connect(sensor, &SensorTag::leftKeyPressed, this, &DevicePluginMultiSensor::onSensorLeftButtonPressed);
connect(sensor, &SensorTag::rightKeyPressed, this, &DevicePluginMultiSensor::onSensorRightButtonPressed);
m_sensors.insert(device, sensor);
sensor->bluetoothDevice()->connectDevice();
return DeviceManager::DeviceSetupStatusSuccess;
}
return DeviceManager::DeviceSetupStatusFailure;
}
void DevicePluginMultiSensor::postSetupDevice(Device *device)
{
// Try to connect right after setup
SensorTag *sensor = m_sensors.value(device);
// Configure sensor with state configurations
sensor->setTemperatureSensorEnabled(device->stateValue(sensorTagTemperatureSensorEnabledStateTypeId).toBool());
sensor->setHumiditySensorEnabled(device->stateValue(sensorTagHumiditySensorEnabledStateTypeId).toBool());
sensor->setPressureSensorEnabled(device->stateValue(sensorTagPressureSensorEnabledStateTypeId).toBool());
sensor->setOpticalSensorEnabled(device->stateValue(sensorTagOpticalSensorEnabledStateTypeId).toBool());
sensor->setAccelerometerEnabled(device->stateValue(sensorTagAccelerometerEnabledStateTypeId).toBool());
sensor->setGyroscopeEnabled(device->stateValue(sensorTagGyroscopeEnabledStateTypeId).toBool());
sensor->setMagnetometerEnabled(device->stateValue(sensorTagMagnetometerEnabledStateTypeId).toBool());
sensor->setMeasurementPeriod(device->stateValue(sensorTagMeasurementPeriodStateTypeId).toInt());
sensor->setMeasurementPeriodMovement(device->stateValue(sensorTagMeasurementPeriodMovementStateTypeId).toInt());
// Connect to the sensor
sensor->bluetoothDevice()->connectDevice();
}
void DevicePluginMultiSensor::deviceRemoved(Device *device)
{
@ -112,10 +132,80 @@ void DevicePluginMultiSensor::deviceRemoved(Device *device)
sensor->deleteLater();
}
DeviceManager::DeviceError DevicePluginMultiSensor::executeAction(Device *device, const Action &action)
{
SensorTag *sensor = m_sensors.value(device);
if (action.actionTypeId() == sensorTagBuzzerActionTypeId) {
sensor->setBuzzerPower(action.param(sensorTagBuzzerStateParamTypeId).value().toBool());
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagGreenLedActionTypeId) {
sensor->setGreenLedPower(action.param(sensorTagGreenLedStateParamTypeId).value().toBool());
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagRedLedActionTypeId) {
sensor->setRedLedPower(action.param(sensorTagRedLedStateParamTypeId).value().toBool());
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagBuzzerImpulseActionTypeId) {
sensor->buzzerImpulse();
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagTemperatureSensorEnabledActionTypeId) {
bool enabled = action.param(sensorTagTemperatureSensorEnabledStateParamTypeId).value().toBool();
device->setStateValue(sensorTagTemperatureSensorEnabledStateTypeId, enabled);
sensor->setTemperatureSensorEnabled(enabled);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagHumiditySensorEnabledActionTypeId) {
bool enabled = action.param(sensorTagHumiditySensorEnabledStateParamTypeId).value().toBool();
device->setStateValue(sensorTagHumiditySensorEnabledStateTypeId, enabled);
sensor->setHumiditySensorEnabled(enabled);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagPressureSensorEnabledActionTypeId) {
bool enabled = action.param(sensorTagPressureSensorEnabledStateParamTypeId).value().toBool();
device->setStateValue(sensorTagPressureSensorEnabledStateTypeId, enabled);
sensor->setPressureSensorEnabled(enabled);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagOpticalSensorEnabledActionTypeId) {
bool enabled = action.param(sensorTagOpticalSensorEnabledStateParamTypeId).value().toBool();
device->setStateValue(sensorTagOpticalSensorEnabledStateTypeId, enabled);
sensor->setOpticalSensorEnabled(enabled);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagAccelerometerEnabledActionTypeId) {
bool enabled = action.param(sensorTagAccelerometerEnabledStateParamTypeId).value().toBool();
device->setStateValue(sensorTagAccelerometerEnabledStateTypeId, enabled);
sensor->setAccelerometerEnabled(enabled);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagGyroscopeEnabledActionTypeId) {
bool enabled = action.param(sensorTagGyroscopeEnabledStateParamTypeId).value().toBool();
device->setStateValue(sensorTagGyroscopeEnabledStateTypeId, enabled);
sensor->setGyroscopeEnabled(enabled);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagMagnetometerEnabledActionTypeId) {
bool enabled = action.param(sensorTagMagnetometerEnabledStateParamTypeId).value().toBool();
device->setStateValue(sensorTagMagnetometerEnabledStateTypeId, enabled);
sensor->setMagnetometerEnabled(enabled);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagMeasurementPeriodActionTypeId) {
int period = action.param(sensorTagMeasurementPeriodStateParamTypeId).value().toInt();
device->setStateValue(sensorTagMeasurementPeriodStateTypeId, period);
sensor->setMeasurementPeriod(period);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagMeasurementPeriodMovementActionTypeId) {
int period = action.param(sensorTagMeasurementPeriodMovementStateParamTypeId).value().toInt();
device->setStateValue(sensorTagMeasurementPeriodMovementStateTypeId, period);
sensor->setMeasurementPeriodMovement(period);
return DeviceManager::DeviceErrorNoError;
} else if (action.actionTypeId() == sensorTagMovementSensitivityActionTypeId) {
int sensitivity = action.param(sensorTagMovementSensitivityStateParamTypeId).value().toInt();
device->setStateValue(sensorTagMovementSensitivityStateTypeId, sensitivity);
sensor->setMovementSensitivity(sensitivity);
return DeviceManager::DeviceErrorNoError;
}
return DeviceManager::DeviceErrorActionTypeNotFound;
}
bool DevicePluginMultiSensor::verifyExistingDevices(const QBluetoothDeviceInfo &deviceInfo)
{
foreach (Device *device, m_sensors.keys()) {
if (device->paramValue(sensortagMacParamTypeId).toString() == deviceInfo.address().toString())
if (device->paramValue(sensorTagMacParamTypeId).toString() == deviceInfo.address().toString())
return true;
}
@ -124,30 +214,20 @@ bool DevicePluginMultiSensor::verifyExistingDevices(const QBluetoothDeviceInfo &
void DevicePluginMultiSensor::onPluginTimer()
{
foreach (SensorTag *sensor, m_sensors) {
sensor->measure();
foreach (SensorTag *sensor, m_sensors.values()) {
if (!sensor->bluetoothDevice()->connected()) {
sensor->bluetoothDevice()->connectDevice();
}
}
}
void DevicePluginMultiSensor::onSensorLeftButtonPressed()
{
SensorTag *sensor = static_cast<SensorTag *>(sender());
emit emitEvent(Event(sensortagLeftKeyEventTypeId, sensor->device()->id()));
}
void DevicePluginMultiSensor::onSensorRightButtonPressed()
{
SensorTag *sensor = static_cast<SensorTag *>(sender());
emit emitEvent(Event(sensortagRightKeyEventTypeId, sensor->device()->id()));
}
void DevicePluginMultiSensor::onBluetoothDiscoveryFinished()
{
BluetoothDiscoveryReply *reply = static_cast<BluetoothDiscoveryReply *>(sender());
if (reply->error() != BluetoothDiscoveryReply::BluetoothDiscoveryReplyErrorNoError) {
qCWarning(dcMultiSensor()) << "Bluetooth discovery error:" << reply->error();
reply->deleteLater();
emit devicesDiscovered(sensortagDeviceClassId, QList<DeviceDescriptor>());
emit devicesDiscovered(sensorTagDeviceClassId, QList<DeviceDescriptor>());
return;
}
@ -155,10 +235,10 @@ void DevicePluginMultiSensor::onBluetoothDiscoveryFinished()
foreach (const QBluetoothDeviceInfo &deviceInfo, reply->discoveredDevices()) {
if (deviceInfo.name().contains("SensorTag")) {
if (!verifyExistingDevices(deviceInfo)) {
DeviceDescriptor descriptor(sensortagDeviceClassId, "Sensor Tag", deviceInfo.address().toString());
DeviceDescriptor descriptor(sensorTagDeviceClassId, "Sensor Tag", deviceInfo.address().toString());
ParamList params;
params.append(Param(sensortagNameParamTypeId, deviceInfo.name()));
params.append(Param(sensortagMacParamTypeId, deviceInfo.address().toString()));
params.append(Param(sensorTagNameParamTypeId, deviceInfo.name()));
params.append(Param(sensorTagMacParamTypeId, deviceInfo.address().toString()));
descriptor.setParams(params);
deviceDescriptors.append(descriptor);
}
@ -166,5 +246,5 @@ void DevicePluginMultiSensor::onBluetoothDiscoveryFinished()
}
reply->deleteLater();
emit devicesDiscovered(sensortagDeviceClassId, deviceDescriptors);
emit devicesDiscovered(sensorTagDeviceClassId, deviceDescriptors);
}

View File

@ -1,7 +1,6 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.io> *
* Copyright (C) 2016 nicc *
* Copyright (C) 2015-2018 Simon Stuerz <simon.stuerz@guh.io> *
* *
* This file is part of nymea. *
* *
@ -41,25 +40,26 @@ class DevicePluginMultiSensor : public DevicePlugin
public:
explicit DevicePluginMultiSensor();
~DevicePluginMultiSensor();
void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
void postSetupDevice(Device *device) override;
void deviceRemoved(Device *device) override;
DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
private:
PluginTimer *m_measureTimer = nullptr;
PluginTimer *m_reconnectTimer = nullptr;
QHash<Device *, SensorTag *> m_sensors;
bool verifyExistingDevices(const QBluetoothDeviceInfo &deviceInfo);
private slots:
void onPluginTimer();
void onSensorLeftButtonPressed();
void onSensorRightButtonPressed();
void onBluetoothDiscoveryFinished();
};
#endif // DEVICEPLUGINMULTISENSOR_H

View File

@ -1,5 +1,5 @@
{
"displayName": "MultiSensor",
"displayName": "Multi Sensor",
"name": "MultiSensor",
"id": "23bf0d8d-df7d-4bee-80ee-f015c5a7f52e",
"vendors": [
@ -9,12 +9,12 @@
"displayName": "Texas Instruments",
"deviceClasses": [
{
"displayName": "Sensor Tag",
"name": "sensortag",
"id": "158a06b6-b27f-4951-957e-6f1e3b44f604",
"name": "sensorTag",
"displayName": "Sensor Tag (CC2650)",
"createMethods": ["discovery"],
"deviceIcon": "Thermometer",
"criticalStateTypeId": "a9629b11-0f34-47f0-a0f0-f758a6aec2b4",
"interfaces": ["temperaturesensor", "humiditysensor", "connectable"],
"basicTags": [
"Device",
"Sensor"
@ -23,14 +23,14 @@
{
"id": "bdb9d684-2f98-45f5-889c-f184c1e73dc7",
"name": "name",
"displayName": "name",
"displayName": "Name",
"type": "QString",
"inputType": "TextLine"
},
{
"id": "d51ed68e-c84a-4136-a5b5-be2f95fd5a0f",
"name": "mac",
"displayName": "mac address",
"displayName": "MAC address",
"type": "QString",
"inputType": "MacAddress"
}
@ -39,29 +39,12 @@
{
"id": "a9629b11-0f34-47f0-a0f0-f758a6aec2b4",
"name": "connected",
"displayName": "connected",
"displayNameEvent": "connected changed",
"displayName": "Connected",
"displayNameEvent": "Connected changed",
"type": "bool",
"cached": false,
"defaultValue": false
},
{
"id": "c664e9ec-a045-49ba-add1-1642ceba7c4f",
"name": "IRtemperature",
"displayName": "IR temperature",
"displayNameEvent": "IR temperature changed",
"type": "double",
"unit": "DegreeCelsius",
"defaultValue": 0
},
{
"id": "e83a50ff-96c9-4b6d-889f-f4238353e794",
"name": "humidity",
"displayName": "humidity",
"displayNameEvent": "humidity changed",
"type": "double",
"unit": "Percentage",
"defaultValue": 0
},
{
"id": "8359ada9-df1c-4e60-bb87-9e21d05ee2e2",
"name": "temperature",
@ -71,34 +54,226 @@
"unit": "DegreeCelsius",
"defaultValue": 0
},
{
"id": "c664e9ec-a045-49ba-add1-1642ceba7c4f",
"name": "objectTemperature",
"displayName": "Object temperature",
"displayNameEvent": "Object temperature changed",
"type": "double",
"unit": "DegreeCelsius",
"defaultValue": 0
},
{
"id": "e83a50ff-96c9-4b6d-889f-f4238353e794",
"name": "humidity",
"displayName": "Humidity",
"displayNameEvent": "Humidity changed",
"type": "double",
"minValue": 0,
"maxValue": 100,
"unit": "Percentage",
"defaultValue": 0
},
{
"id": "645633ad-77d4-45b2-8be8-d6ca7a12eb7a",
"name": "pressure",
"displayName": "pressure",
"displayNameEvent": "pressure changed",
"displayName": "Barometric pressure",
"displayNameEvent": "Barometric pressure changed",
"type": "double",
"unit": "HectoPascal",
"defaultValue": 0
},
{
"id": "4be5ca26-0565-419d-b18b-2a5a385d2a3d",
"name": "moving",
"displayName": "moving",
"displayNameEvent": "moving changed",
"type": "bool",
"defaultValue": false
}
],
"eventTypes": [
{
"id": "61478490-bed0-4fed-9d58-f13c35b4f220",
"name": "leftKey",
"displayName": "left key pressed"
"id": "6635dce4-2d8d-4608-a836-768c3014f356",
"name": "lightIntensity",
"displayName": "Light intensity",
"displayNameEvent": "Light intensity changed",
"type": "double",
"unit": "Lux",
"defaultValue": 0
},
{
"id": "b7e927db-af28-4fdc-8eb7-edb02258ff5a",
"name": "rightKey",
"displayName": "right key pressed"
"id": "4be5ca26-0565-419d-b18b-2a5a385d2a3d",
"name": "moving",
"displayName": "Moving",
"displayNameEvent": "Moving changed",
"type": "bool",
"cached": false,
"defaultValue": false
},
{
"id": "758d9b39-7390-40f5-8e19-d8b0f4a0a0c6",
"name": "magnetDetected",
"displayName": "Magnet detected",
"displayNameEvent": "Magnet detected changed",
"type": "bool",
"cached": false,
"defaultValue": false
},
{
"id": "8995e49e-ca2d-4dd9-a22f-de6c566c2115",
"name": "leftButtonPressed",
"displayName": "Left button pressed",
"displayNameEvent": "Left button pressed changed",
"type": "bool",
"cached": false,
"defaultValue": false
},
{
"id": "ef8eedc5-6a45-4dfb-bb55-ada1a931b20b",
"name": "rightButtonPressed",
"displayName": "Right button pressed",
"displayNameEvent": "Right button pressed changed",
"type": "bool",
"cached": false,
"defaultValue": false
},
{
"id": "8d692132-f950-486f-b3dd-fe1ebc574e1d",
"name": "greenLed",
"displayName": "Green LED",
"displayNameEvent": "Green LED power changed",
"displayNameAction": "Set green LED power",
"type": "bool",
"cached": false,
"defaultValue": false,
"writable": true
},
{
"id": "bb585725-6393-42de-aea2-ea4f525ad348",
"name": "redLed",
"displayName": "Red LED",
"displayNameEvent": "Red LED power changed",
"displayNameAction": "Set red LED power",
"type": "bool",
"cached": false,
"defaultValue": false,
"writable": true
},
{
"id": "d522c536-4427-4c53-9980-7820b2649aad",
"name": "buzzer",
"displayName": "Buzzer",
"displayNameEvent": "Buzzer power changed",
"displayNameAction": "Set buzzer power",
"type": "bool",
"cached": false,
"defaultValue": false,
"writable": true
},
{
"id": "6f0e40a2-0f97-4c1e-8229-757e3c18b345",
"name": "temperatureSensorEnabled",
"displayName": "Temperature sensor enabled",
"displayNameEvent": "Temperature sensor enabled changed",
"displayNameAction": "Set temperature sensor enabled",
"type": "bool",
"defaultValue": true,
"writable": true
},
{
"id": "29881172-626a-42d5-83b8-3e2e5ca533be",
"name": "humiditySensorEnabled",
"displayName": "Humidity sensor enabled",
"displayNameEvent": "Humidity sensor enabled changed",
"displayNameAction": "Set humidity sensor enabled",
"type": "bool",
"defaultValue": true,
"writable": true
},
{
"id": "50e5e282-9707-4b31-bb3f-a6ca30a7e1ff",
"name": "pressureSensorEnabled",
"displayName": "Pressure sensor enabled",
"displayNameEvent": "Pressure sensor enabled changed",
"displayNameAction": "Set pressure sensor enabled",
"type": "bool",
"defaultValue": true,
"writable": true
},
{
"id": "1460a6d6-9fb4-4385-b27b-ee4b7594e454",
"name": "opticalSensorEnabled",
"displayName": "Optical sensor enabled",
"displayNameEvent": "Optical sensor enabled changed",
"displayNameAction": "Set optical sensor enabled",
"type": "bool",
"defaultValue": true,
"writable": true
},
{
"id": "5786c91a-d94d-461a-8d22-f978dd1438ab",
"name": "accelerometerEnabled",
"displayName": "Accelerometer enabled",
"displayNameEvent": "Accelerometer enabled changed",
"displayNameAction": "Set accelerometer enabled",
"type": "bool",
"defaultValue": true,
"writable": true
},
{
"id": "94517544-cb97-4816-8993-cb4cf2651a1e",
"name": "gyroscopeEnabled",
"displayName": "Gyroscope enabled",
"displayNameEvent": "Gyroscope enabled changed",
"displayNameAction": "Set gyroscope enabled",
"type": "bool",
"defaultValue": true,
"writable": true
},
{
"id": "96aae111-b1c1-48a1-9b1f-b56efa546d0d",
"name": "magnetometerEnabled",
"displayName": "Magnetometer enabled",
"displayNameEvent": "Magnetometer enabled changed",
"displayNameAction": "Set magnetometer enabled",
"type": "bool",
"defaultValue": true,
"writable": true
},
{
"id": "c5308565-5dc9-409e-ae99-577c212c7a92",
"name": "measurementPeriod",
"displayName": "Measurement period for enviromental sensors",
"displayNameEvent": "Measurement period for enviromental sensors changed",
"displayNameAction": "Set measurement period for enviromental sensors",
"type": "int",
"minValue": 10,
"maxValue": 2500,
"defaultValue": 2000,
"writable": true
},
{
"id": "5237c89c-c21d-4d78-ac99-8be661b40da7",
"name": "measurementPeriodMovement",
"displayName": "Measurement period movement sensor",
"displayNameEvent": "Measurement period movement sensor changed",
"displayNameAction": "Set measurement period movement sensor",
"type": "int",
"minValue": 10,
"maxValue": 2500,
"defaultValue": 300,
"writable": true
},
{
"id": "a3298d16-eea6-4474-9061-90466e92d476",
"name": "movementSensitivity",
"displayName": "Movement sensitivity",
"displayNameEvent": "Movement sensitivity changed",
"displayNameAction": "Set movement sensitivity",
"type": "int",
"unit": "Percentage",
"minValue": 0,
"maxValue": 100,
"defaultValue": 40,
"writable": true
}
],
"actionTypes": [
{
"id": "a048ab2e-4f17-4467-a166-a7572156c07e",
"name": "buzzerImpulse",
"displayName": "Buzzer impulse"
}
]
}

View File

@ -0,0 +1,15 @@
# Autocreated plot script for system disk usage
set term png small size 2000,1000
set output "multisensor.png"
set title "Multisensor filter"
set xlabel "Time"
set ylabel "Value"
set xdata time
set timefmt "%s"
set xtics format "%H:%M:%S"
set yrange [0:*]
set grid
plot "/tmp/multisensor.log" using 1:2 with lines title "Original value", \
"/tmp/multisensor.log" using 1:3 with lines title "Filtered value"

View File

@ -5,9 +5,13 @@ TARGET = $$qtLibraryTarget(nymea_devicepluginmultisensor)
SOURCES += \
devicepluginmultisensor.cpp \
#sensortag-old.cpp \
sensortag.cpp
sensortag.cpp \
sensorfilter.cpp \
sensordataprocessor.cpp
HEADERS += \
devicepluginmultisensor.h \
#sensortag-old.h \
sensortag.h
sensortag.h \
sensorfilter.h \
sensordataprocessor.h

View File

@ -0,0 +1,329 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015-2018 Simon Stuerz <simon.stuerz@guh.io> *
* *
* This file is part of nymea. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; If not, see *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "sensordataprocessor.h"
#include "extern-plugininfo.h"
#include "math.h"
#include <QVector3D>
#include <QByteArray>
#include <QDataStream>
#include <QDateTime>
SensorDataProcessor::SensorDataProcessor(Device *device, QObject *parent) :
QObject(parent),
m_device(device)
{
// Create data filters
m_temperatureFilter = new SensorFilter(SensorFilter::TypeLowPass, this);
m_temperatureFilter->setLowPassAlpha(0.1);
m_temperatureFilter->setFilterWindowSize(30);
m_objectTemperatureFilter = new SensorFilter(SensorFilter::TypeLowPass, this);
m_objectTemperatureFilter->setLowPassAlpha(0.4);
m_objectTemperatureFilter->setFilterWindowSize(20);
m_humidityFilter = new SensorFilter(SensorFilter::TypeLowPass, this);
m_humidityFilter->setLowPassAlpha(0.1);
m_humidityFilter->setFilterWindowSize(30);
m_pressureFilter = new SensorFilter(SensorFilter::TypeLowPass, this);
m_pressureFilter->setLowPassAlpha(0.1);
m_pressureFilter->setFilterWindowSize(30);
m_opticalFilter = new SensorFilter(SensorFilter::TypeLowPass, this);
m_opticalFilter->setLowPassAlpha(0.01);
m_opticalFilter->setFilterWindowSize(10);
m_accelerometerFilter = new SensorFilter(SensorFilter::TypeLowPass, this);
m_accelerometerFilter->setLowPassAlpha(0.6);
m_accelerometerFilter->setFilterWindowSize(40);
// Check if the data should be logged
if (m_filterDebug) {
m_logFile = new QFile("/tmp/multisensor.log", this);
if (!m_logFile->open(QIODevice::Append | QIODevice::Text)) {
qCWarning(dcMultiSensor()) << "Could not open log file" << m_logFile->fileName();
delete m_logFile;
m_logFile = nullptr;
}
}
}
SensorDataProcessor::~SensorDataProcessor()
{
if (m_logFile) {
m_logFile->close();
}
}
void SensorDataProcessor::setAccelerometerRange(int accelerometerRange)
{
m_accelerometerRange = accelerometerRange;
}
void SensorDataProcessor::setMovementSensitivity(int movementSensitivity)
{
m_movementSensitivity = movementSensitivity;
}
double SensorDataProcessor::roundValue(float value)
{
int tmpValue = static_cast<int>(value * 10);
return static_cast<double>(tmpValue) / 10.0;
}
bool SensorDataProcessor::testBitUint8(quint8 value, int bitPosition)
{
return (((value)>> (bitPosition)) & 1);
}
void SensorDataProcessor::processTemperatureData(const QByteArray &data)
{
Q_ASSERT(data.count() == 4);
quint16 rawObjectTemperature = 0;
quint16 rawAmbientTemperature = 0;
QByteArray payload(data);
QDataStream stream(&payload, QIODevice::ReadOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream >> rawObjectTemperature >> rawAmbientTemperature ;
double scaleFactor = 0.03125;
double objectTemperature = static_cast<double>(rawObjectTemperature) / 4 * scaleFactor;
double ambientTemperature = static_cast<double>(rawAmbientTemperature) / 4 * scaleFactor;
//qCDebug(dcMultiSensor()) << "Temperature value" << data.toHex();
//qCDebug(dcMultiSensor()) << "Object temperature" << roundValue(objectTemperature) << "°C";
//qCDebug(dcMultiSensor()) << "Ambient temperature" << roundValue(ambientTemperature) << "°C";
double objectTemperatureFiltered = m_objectTemperatureFilter->filterValue(objectTemperature);
double ambientTemperatureFiltered = m_temperatureFilter->filterValue(ambientTemperature);
if (m_objectTemperatureFilter->isReady()) {
m_device->setStateValue(sensorTagObjectTemperatureStateTypeId, roundValue(objectTemperatureFiltered));
}
// Note: only change the state once the filter has collected enought data
if (m_temperatureFilter->isReady()) {
m_device->setStateValue(sensorTagTemperatureStateTypeId, roundValue(ambientTemperatureFiltered));
}
}
void SensorDataProcessor::processKeyData(const QByteArray &data)
{
Q_ASSERT(data.count() == 1);
quint8 flags = static_cast<quint8>(data.at(0));
setLeftButtonPressed(testBitUint8(flags, 0));
setRightButtonPressed(testBitUint8(flags, 1));
setMagnetDetected(testBitUint8(flags, 2));
}
void SensorDataProcessor::processHumidityData(const QByteArray &data)
{
Q_ASSERT(data.count() == 4);
quint16 rawHumidityTemperature = 0;
quint16 rawHumidity = 0;
QByteArray payload(data);
QDataStream stream(&payload, QIODevice::ReadOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream >> rawHumidityTemperature >> rawHumidity ;
// Note: we don't need the temperature measurement from the humidity sensor
//double humidityTemperature = (rawHumidityTemperature / 65536.0 * 165.0) - 40;
double humidity = rawHumidity / 65536.0 * 100.0;
double humidityFiltered = m_humidityFilter->filterValue(humidity);
if (m_humidityFilter->isReady()) {
m_device->setStateValue(sensorTagHumidityStateTypeId, roundValue(humidityFiltered));
}
}
void SensorDataProcessor::processPressureData(const QByteArray &data)
{
Q_ASSERT(data.count() == 6);
QByteArray temperatureData(data.left(3));
quint32 rawTemperature = static_cast<quint8>(temperatureData.at(2));
rawTemperature <<= 8;
rawTemperature |= static_cast<quint8>(temperatureData.at(1));
rawTemperature <<= 8;
rawTemperature |= static_cast<quint8>(temperatureData.at(0));
QByteArray pressureData(data.right(3));
quint32 rawPressure = static_cast<quint8>(pressureData.at(2));
rawPressure <<= 8;
rawPressure |= static_cast<quint8>(pressureData.at(1));
rawPressure <<= 8;
rawPressure |= static_cast<quint8>(pressureData.at(0));
// Note: we don't need the temperature measurement from the barometic pressure sensor
//qCDebug(dcMultiSensor()) << "Pressure temperature:" << roundValue(rawTemperature / 100.0) << "°C";
//qCDebug(dcMultiSensor()) << "Pressure:" << roundValue(rawPressure / 100.0) << "mBar";
double pressureFiltered = m_pressureFilter->filterValue(rawPressure / 100.0);
if (m_pressureFilter->isReady()) {
m_device->setStateValue(sensorTagPressureStateTypeId, roundValue(pressureFiltered));
}
}
void SensorDataProcessor::processOpticalData(const QByteArray &data)
{
Q_ASSERT(data.count() == 2);
quint16 rawOptical = 0;
QByteArray payload(data);
QDataStream stream(&payload, QIODevice::ReadOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream >> rawOptical;
quint16 lumm = rawOptical & 0x0FFF;
quint16 lume = (rawOptical & 0xF000) >> 12;
double lux = lumm * (0.01 * pow(2,lume));
//qCDebug(dcMultiSensor()) << "Lux:" << lux;
double luxFiltered = m_opticalFilter->filterValue(lux);
if (m_opticalFilter->isReady()) {
m_device->setStateValue(sensorTagLightIntensityStateTypeId, qRound(luxFiltered));
}
logSensorValue(lux, qRound(luxFiltered));
}
void SensorDataProcessor::processMovementData(const QByteArray &data)
{
//qCDebug(dcMultiSensor()) << "--> Movement value" << data.toHex();
QByteArray payload(data);
QDataStream stream(&payload, QIODevice::ReadOnly);
stream.setByteOrder(QDataStream::LittleEndian);
qint16 gyroXRaw = 0; qint16 gyroYRaw = 0; qint16 gyroZRaw = 0;
stream >> gyroXRaw >> gyroYRaw >> gyroZRaw;
qint16 accXRaw = 0; qint16 accYRaw = 0; qint16 accZRaw = 0;
stream >> accXRaw >> accYRaw >> accZRaw;
qint16 magXRaw = 0; qint16 magYRaw = 0; qint16 magZRaw = 0;
stream >> magXRaw >> magYRaw >> magZRaw;
// Calculate rotation [deg/s], Range +- 250
double gyroX = static_cast<double>(gyroXRaw) / (65536 / 500);
double gyroY = static_cast<double>(gyroYRaw) / (65536 / 500);
double gyroZ = static_cast<double>(gyroZRaw) / (65536 / 500);
// Calculate acceleration [G], Range +- m_accelerometerRange
double accX = static_cast<double>(accXRaw) / (32768 / static_cast<int>(m_accelerometerRange));
double accY = static_cast<double>(accYRaw) / (32768 / static_cast<int>(m_accelerometerRange));
double accZ = static_cast<double>(accZRaw) / (32768 / static_cast<int>(m_accelerometerRange));
// Calculate magnetism [uT], Range +- 4900
double magX = static_cast<double>(magXRaw);
double magY = static_cast<double>(magYRaw);
double magZ = static_cast<double>(magZRaw);
//qCDebug(dcMultiSensor()) << "Accelerometer x:" << accX << " y:" << accY << " z:" << accZ;
//qCDebug(dcMultiSensor()) << "Gyroscope x:" << gyroX << " y:" << gyroY << " z:" << gyroZ;
//qCDebug(dcMultiSensor()) << "Magnetometer x:" << magX << " y:" << magY << " z:" << magZ;
QVector3D accelerometerVector(accX, accY, accZ);
QVector3D gyroscopeVector(gyroX, gyroY, gyroZ);
QVector3D magnetometerVector(magX, magY, magZ);
Q_UNUSED(gyroscopeVector)
Q_UNUSED(magnetometerVector)
double filteredVectorLength = m_accelerometerFilter->filterValue(accelerometerVector.length());
// Initialize the accelerometer value if no data known yet
if (m_lastAccelerometerVectorLenght == -99999) {
m_lastAccelerometerVectorLenght = filteredVectorLength;
return;
}
double delta = qAbs(qAbs(m_lastAccelerometerVectorLenght) - qAbs(filteredVectorLength));
bool motionDetected = (delta >= m_movementSensitivity);
m_device->setStateValue(sensorTagMovingStateTypeId, motionDetected);
m_lastAccelerometerVectorLenght = filteredVectorLength;
}
void SensorDataProcessor::reset()
{
m_lastAccelerometerVectorLenght = -99999;
// Reset data filters
m_temperatureFilter->reset();
m_objectTemperatureFilter->reset();
m_humidityFilter->reset();
m_pressureFilter->reset();
m_opticalFilter->reset();
m_accelerometerFilter->reset();
}
void SensorDataProcessor::setLeftButtonPressed(bool pressed)
{
if (m_leftButtonPressed == pressed)
return;
qCDebug(dcMultiSensor()) << "Left button" << (pressed ? "pressed" : "released");
m_leftButtonPressed = pressed;
m_device->setStateValue(sensorTagLeftButtonPressedStateTypeId, m_leftButtonPressed);
}
void SensorDataProcessor::setRightButtonPressed(bool pressed)
{
if (m_rightButtonPressed == pressed)
return;
qCDebug(dcMultiSensor()) << "Right button" << (pressed ? "pressed" : "released");
m_rightButtonPressed = pressed;
m_device->setStateValue(sensorTagRightButtonPressedStateTypeId, m_rightButtonPressed);
}
void SensorDataProcessor::setMagnetDetected(bool detected)
{
if (m_magnetDetected == detected)
return;
qCDebug(dcMultiSensor()) << "Magnet detector" << (detected ? "active" : "inactive");
m_magnetDetected = detected;
m_device->setStateValue(sensorTagMagnetDetectedStateTypeId, m_magnetDetected);
}
void SensorDataProcessor::logSensorValue(double originalValue, double filteredValue)
{
if (!m_filterDebug || !m_logFile)
return;
QString logLine = QString("%1 %2 %3\n").arg(QDateTime::currentDateTime().toTime_t()).arg(originalValue).arg(filteredValue);
QTextStream logStream(m_logFile);
logStream.setCodec("UTF-8");
logStream << logLine;
}

View File

@ -0,0 +1,93 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015-2018 Simon Stuerz <simon.stuerz@guh.io> *
* *
* This file is part of nymea. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; If not, see *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef SENSORDATAPROCESSOR_H
#define SENSORDATAPROCESSOR_H
#include <QFile>
#include <QObject>
#include "plugin/device.h"
#include "extern-plugininfo.h"
#include "sensorfilter.h"
class SensorDataProcessor : public QObject
{
Q_OBJECT
public:
explicit SensorDataProcessor(Device *device, QObject *parent = nullptr);
~SensorDataProcessor();
void setAccelerometerRange(int accelerometerRange);
void setMovementSensitivity(int movementSensitivity);
static double roundValue(float value);
static bool testBitUint8(quint8 value, int bitPosition);
void processTemperatureData(const QByteArray &data);
void processKeyData(const QByteArray &data);
void processHumidityData(const QByteArray &data);
void processPressureData(const QByteArray &data);
void processOpticalData(const QByteArray &data);
void processMovementData(const QByteArray &data);
void reset();
private:
Device *m_device = nullptr;
double m_lastAccelerometerVectorLenght = -99999;
int m_accelerometerRange = 16;
double m_movementSensitivity = 0.5;
bool m_leftButtonPressed = false;
bool m_rightButtonPressed = false;
bool m_magnetDetected = false;
// Log sensor data for debugging filters
// Note: set this to true for enable sensor filter logging
bool m_filterDebug = true;
QFile *m_logFile = nullptr;
SensorFilter *m_temperatureFilter = nullptr;
SensorFilter *m_objectTemperatureFilter = nullptr;
SensorFilter *m_humidityFilter = nullptr;
SensorFilter *m_pressureFilter = nullptr;
SensorFilter *m_opticalFilter = nullptr;
SensorFilter *m_accelerometerFilter = nullptr;
// Set methods
void setLeftButtonPressed(bool pressed);
void setRightButtonPressed(bool pressed);
void setMagnetDetected(bool detected);
void logSensorValue(double originalValue, double filteredValue);
signals:
private slots:
};
#endif // SENSORDATAPROCESSOR_H

View File

@ -0,0 +1,178 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015-2018 Simon Stuerz <simon.stuerz@guh.io> *
* *
* This file is part of nymea. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; If not, see *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "sensorfilter.h"
#include <QDebug>
SensorFilter::SensorFilter(Type filterType, QObject *parent) :
QObject(parent),
m_filterType(filterType)
{
}
double SensorFilter::filterValue(double value)
{
double resultValue = value;
switch (m_filterType) {
case TypeLowPass:
resultValue = lowPassFilterValue(value);
break;
case TypeHighPass:
resultValue = highPassFilterValue(value);
break;
case TypeAverage:
resultValue = averageFilterValue(value);
break;
default:
break;
}
return resultValue;
}
bool SensorFilter::isReady() const
{
// Note: filter is ready once 10% of window filled
return m_inputData.size() >= m_filterWindowSize * 0.1;
}
void SensorFilter::reset()
{
m_averageSum = 0;
m_inputData.clear();
}
SensorFilter::Type SensorFilter::filterType() const
{
return m_filterType;
}
QVector<double> SensorFilter::inputData() const
{
return m_inputData;
}
QVector<double> SensorFilter::outputData() const
{
return m_outputData;
}
uint SensorFilter::windowSize() const
{
return m_filterWindowSize;
}
void SensorFilter::setFilterWindowSize(uint windowSize)
{
Q_ASSERT_X(windowSize > 0, "value out of range", "The filter window size must be bigger than 0");
m_filterWindowSize = windowSize;
}
double SensorFilter::lowPassAlpha() const
{
return m_lowPassAlpha;
}
void SensorFilter::setLowPassAlpha(double alpha)
{
Q_ASSERT_X(alpha > 0 && alpha <= 1, "value out of range", "The alpha low pass filter value must be [ 0 < alpha <= 1 ]");
m_lowPassAlpha = alpha;
}
double SensorFilter::highPassAlpha() const
{
return m_highPassAlpha;
}
void SensorFilter::setHighPassAlpha(double alpha)
{
Q_ASSERT_X(alpha > 0 && alpha <= 1, "value out of range", "The alpha high pass filter value must be [ 0 < alpha <= 1 ]");
m_highPassAlpha = alpha;
}
void SensorFilter::addInputValue(double value)
{
m_inputData.append(value);
if (m_inputData.size() > m_filterWindowSize) {
m_inputData.removeFirst();
}
}
double SensorFilter::lowPassFilterValue(double value)
{
addInputValue(value);
// Check if we have enought data for filtering
if (m_inputData.size() < 2) {
return value;
}
QVector<double> outputData;
outputData.append(m_inputData.at(0));
for (int i = 1; i < m_inputData.size(); i++) {
// y[i] := y[i-1] + α * (x[i] - y[i-1])
outputData.append(outputData.at(i - 1) + m_lowPassAlpha * (m_inputData.at(i) - outputData.at(i - 1)));
}
m_outputData = outputData;
return m_outputData.last();
}
double SensorFilter::highPassFilterValue(double value)
{
addInputValue(value);
// Check if we have enought data for filtering
if (m_inputData.size() < 2) {
return value;
}
QVector<double> outputData;
outputData.append(m_inputData.at(0));
for (int i = 1; i < m_inputData.size(); i++) {
// y[i] := α * y[i-1] + α * (x[i] - x[i-1])
outputData.append(m_highPassAlpha * outputData.at(i - 1) + m_highPassAlpha * (m_inputData.at(i) - m_inputData.at(i - 1)));
}
m_outputData = outputData;
return m_outputData.last();
}
double SensorFilter::averageFilterValue(double value)
{
if (m_inputData.isEmpty()) {
addInputValue(value);
m_averageSum = value;
return value;
}
if (m_inputData.size() >= m_filterWindowSize) {
m_averageSum -= m_inputData.takeFirst();
}
addInputValue(value);
m_averageSum += value;
return m_averageSum / m_inputData.size();
}

View File

@ -0,0 +1,81 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015-2018 Simon Stuerz <simon.stuerz@guh.io> *
* *
* This file is part of nymea. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; If not, see *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef SENSORFILTER_H
#define SENSORFILTER_H
#include <QObject>
#include <QVector>
class SensorFilter : public QObject
{
Q_OBJECT
public:
enum Type {
TypeLowPass,
TypeHighPass,
TypeAverage
};
Q_ENUM(Type)
explicit SensorFilter(Type filterType, QObject *parent = nullptr);
double filterValue(double value);
bool isReady() const;
void reset();
Type filterType() const;
QVector<double> inputData() const;
QVector<double> outputData() const;
// Filter configuration
uint windowSize() const;
void setFilterWindowSize(uint windowSize = 20);
double lowPassAlpha() const;
void setLowPassAlpha(double alpha = 0.2);
double highPassAlpha() const;
void setHighPassAlpha(double alpha = 0.2);
private:
Type m_filterType = TypeLowPass;
int m_filterWindowSize = 20;
double m_lowPassAlpha = 0.2;
double m_highPassAlpha = 0.2;
double m_averageSum = 0;
QVector<double> m_inputData;
QVector<double> m_outputData;
void addInputValue(double value);
// Filter methods
double lowPassFilterValue(double value);
double highPassFilterValue(double value);
double averageFilterValue(double value);
};
#endif // SENSORFILTER_H

View File

@ -1,10 +1,38 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015-2018 Simon Stuerz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "sensortag.h"
#include "extern-plugininfo.h"
#include "math.h"
#include <QTimer>
#include <QVector3D>
#include <QDataStream>
SensorTag::SensorTag(Device *device, BluetoothLowEnergyDevice *bluetoothDevice, QObject *parent) :
QObject(parent),
m_device(device),
m_bluetoothDevice(bluetoothDevice)
m_bluetoothDevice(bluetoothDevice),
m_dataProcessor(new SensorDataProcessor(m_device, this))
{
connect(m_bluetoothDevice, &BluetoothLowEnergyDevice::connectedChanged, this, &SensorTag::onConnectedChanged);
connect(m_bluetoothDevice, &BluetoothLowEnergyDevice::servicesDiscoveryFinished, this, &SensorTag::onServiceDiscoveryFinished);
@ -20,111 +48,404 @@ BluetoothLowEnergyDevice *SensorTag::bluetoothDevice()
return m_bluetoothDevice;
}
void SensorTag::updateInfraredValue(const QByteArray &value)
void SensorTag::setTemperatureSensorEnabled(bool enabled)
{
qCDebug(dcMultiSensor()) << "Infrared value" << value;
qCDebug(dcMultiSensor()) << "Temperature sensor" << (enabled ? "enabled" : "disabled");
if (m_temperatureEnabled == enabled)
return;
m_temperatureEnabled = enabled;
setTemperatureSensorPower(m_temperatureEnabled);
}
void SensorTag::updateButtonValue(const QByteArray &value)
void SensorTag::setHumiditySensorEnabled(bool enabled)
{
const quint8 *data = reinterpret_cast<const quint8 *>(value.constData());
if (*data & 1)
emit leftKeyPressed();
if (*data & 2)
emit rightKeyPressed();
qCDebug(dcMultiSensor()) << "Humidity sensor" << (enabled ? "enabled" : "disabled");
if (m_humidityEnabled == enabled)
return;
m_humidityEnabled = enabled;
setHumiditySensorPower(m_humidityEnabled);
}
void SensorTag::updateHumidityValue(const QByteArray &value)
void SensorTag::setPressureSensorEnabled(bool enabled)
{
qCDebug(dcMultiSensor()) << "Humidity value" << value;
qCDebug(dcMultiSensor()) << "Pressure sensor" << (enabled ? "enabled" : "disabled");
if (m_pressureEnabled == enabled)
return;
m_pressureEnabled = enabled;
setPressureSensorPower(m_pressureEnabled);
}
void SensorTag::updatePressureValue(const QByteArray &value)
void SensorTag::setOpticalSensorEnabled(bool enabled)
{
qCDebug(dcMultiSensor()) << "Pressure value" << value;
qCDebug(dcMultiSensor()) << "Optical sensor" << (enabled ? "enabled" : "disabled");
if (m_opticalEnabled == enabled)
return;
m_opticalEnabled = enabled;
setOpticalSensorPower(m_opticalEnabled);
}
void SensorTag::setAccelerometerEnabled(bool enabled)
{
qCDebug(dcMultiSensor()) << "Accelerometer" << (enabled ? "enabled" : "disabled");
if (m_accelerometerEnabled == enabled)
return;
m_accelerometerEnabled = enabled;
configureMovement();
}
void SensorTag::setAccelerometerRange(const SensorTag::SensorAccelerometerRange &range)
{
qCDebug(dcMultiSensor()) << "Accelerometer" << range;
if (m_accelerometerRange == range)
return;
m_accelerometerRange = range;
configureMovement();
}
void SensorTag::setGyroscopeEnabled(bool enabled)
{
qCDebug(dcMultiSensor()) << "Gyroscope" << (enabled ? "enabled" : "disabled");
if (m_gyroscopeEnabled == enabled)
return;
m_gyroscopeEnabled = enabled;
configureMovement();
}
void SensorTag::setMagnetometerEnabled(bool enabled)
{
qCDebug(dcMultiSensor()) << "Magnetometer" << (enabled ? "enabled" : "disabled");
if (m_magnetometerEnabled == enabled)
return;
m_magnetometerEnabled = enabled;
configureMovement();
}
void SensorTag::setMeasurementPeriod(int period)
{
qCDebug(dcMultiSensor()) << "Set sensor measurement period to" << period << "ms";
if (period % 10 != 0) {
int adjustedValue = qRound(static_cast<float>(period) / 10.0) * 10;
qCWarning(dcMultiSensor()) << "Measurement period of sensors" << period << "must be a multiple of 10ms. Adjusting it to" << adjustedValue;
period = adjustedValue;
}
m_temperaturePeriod = period;
if (m_temperatureService && m_temperaturePeriodCharacteristic.isValid())
configurePeriod(m_temperatureService, m_temperaturePeriodCharacteristic, m_temperaturePeriod);
m_humidityPeriod = period;
if (m_humidityService && m_humidityPeriodCharacteristic.isValid())
configurePeriod(m_humidityService, m_humidityPeriodCharacteristic, m_humidityPeriod);
m_pressurePeriod = period;
if (m_pressureService && m_pressurePeriodCharacteristic.isValid())
configurePeriod(m_pressureService, m_pressurePeriodCharacteristic, m_pressurePeriod);
m_opticalPeriod = period;
if (m_opticalService && m_opticalPeriodCharacteristic.isValid())
configurePeriod(m_opticalService, m_opticalPeriodCharacteristic, m_opticalPeriod);
}
void SensorTag::setMeasurementPeriodMovement(int period)
{
qCDebug(dcMultiSensor()) << "Set movement sensor measurement period to" << period << "ms";
if (period % 10 != 0) {
int adjustedValue = qRound(static_cast<float>(period) / 10.0) * 10;
qCWarning(dcMultiSensor()) << "Measurement period of movement sensor" << period << "must be a multiple of 10ms. Adjusting it to" << adjustedValue;
period = adjustedValue;
}
m_movementPeriod = period;
if (m_movementService && m_movementPeriodCharacteristic.isValid())
configurePeriod(m_movementService, m_movementPeriodCharacteristic, m_movementPeriod);
}
void SensorTag::setMovementSensitivity(int percentage)
{
m_movementSensitivity = static_cast<double>(percentage) / 100.0;
}
void SensorTag::setGreenLedPower(bool power)
{
m_greenLedEnabled = power;
qCDebug(dcMultiSensor()) << "Green LED" << (power ? "enabled" : "disabled");
configureIo();
m_device->setStateValue(sensorTagGreenLedStateTypeId, m_greenLedEnabled);
}
void SensorTag::setRedLedPower(bool power)
{
m_redLedEnabled = power;
qCDebug(dcMultiSensor()) << "Red LED" << (power ? "enabled" : "disabled");
configureIo();
m_device->setStateValue(sensorTagRedLedStateTypeId, m_redLedEnabled);
}
void SensorTag::setBuzzerPower(bool power)
{
m_buzzerEnabled = power;
qCDebug(dcMultiSensor()) << "Buzzer" << (power ? "enabled" : "disabled");
configureIo();
m_device->setStateValue(sensorTagBuzzerStateTypeId, m_buzzerEnabled);
}
void SensorTag::buzzerImpulse()
{
qCDebug(dcMultiSensor()) << "Buzzer impulse";
setBuzzerPower(true);
QTimer::singleShot(1000, this, &SensorTag::onBuzzerImpulseTimeout);
}
void SensorTag::configurePeriod(QLowEnergyService *serice, const QLowEnergyCharacteristic &characteristic, int measurementPeriod)
{
Q_ASSERT(measurementPeriod % 10 == 0);
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream << static_cast<quint8>(measurementPeriod / 10);
qCDebug(dcMultiSensor()) << "Configure period to" << measurementPeriod << payload.toHex();
serice->writeCharacteristic(characteristic, payload);
}
void SensorTag::configureMovement()
{
if (!m_movementService || !m_movementConfigurationCharacteristic.isValid())
return;
quint16 configuration = 0;
if (m_gyroscopeEnabled) {
configuration |= (1 << 0); // enable x-axis
configuration |= (1 << 1); // enable y-axis
configuration |= (1 << 2); // enable z-axis
}
if (m_accelerometerEnabled) {
configuration |= (1 << 3); // enable x-axis
configuration |= (1 << 4); // enable y-axis
configuration |= (1 << 5); // enable z-axis
}
if (m_magnetometerEnabled) {
configuration |= (1 << 6); // enable all axis
}
// Always enable wake on movement in order to save energy
configuration |= (1 << 8); // enable
// Accelerometer range 2 Bit ( 0 = 2G, 1 = 4G, 2 = 8G, 3 = 16G)
switch (m_accelerometerRange) {
case SensorAccelerometerRange2G:
// Bit 9 = 0
// Bit 10 = 0
break;
case SensorAccelerometerRange4G:
configuration |= (1 << 11);
// Bit 12 = 0
break;
case SensorAccelerometerRange8G:
// Bit 13 = 0
configuration |= (1 << 14);
break;
case SensorAccelerometerRange16G:
configuration |= (1 << 15);
configuration |= (1 << 16);
break;
default:
break;
}
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << configuration;
qCDebug(dcMultiSensor()) << "Configure movement sensor" << data.toHex();
m_movementService->writeCharacteristic(m_movementConfigurationCharacteristic, data);
}
void SensorTag::configureSensorMode(const SensorTag::SensorMode &mode)
{
if (!m_ioService || !m_ioDataCharacteristic.isValid())
return;
qCDebug(dcMultiSensor()) << "Setting" << mode;
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << static_cast<quint8>(mode);
m_ioService->writeCharacteristic(m_ioConfigurationCharacteristic, data);
}
void SensorTag::configureIo()
{
if (!m_ioService || !m_ioDataCharacteristic.isValid())
return;
// Write value to IO
quint8 configuration = 0;
if (m_redLedEnabled)
configuration |= (1 << 0); // Red LED
if (m_greenLedEnabled)
configuration |= (1 << 1); // Green LED
if (m_buzzerEnabled)
configuration |= (1 << 2); // Buzzer
QByteArray payload;
QDataStream stream(&payload, QIODevice::WriteOnly);
stream << configuration;
m_ioService->writeCharacteristic(m_ioDataCharacteristic, payload);
}
void SensorTag::setTemperatureSensorPower(bool power)
{
if (!m_temperatureService || !m_temperatureConfigurationCharacteristic.isValid())
return;
QByteArray payload = (power ? QByteArray::fromHex("01") : QByteArray::fromHex("00"));
m_temperatureService->writeCharacteristic(m_temperatureConfigurationCharacteristic, payload);
}
void SensorTag::setHumiditySensorPower(bool power)
{
if (!m_humidityService || !m_humidityConfigurationCharacteristic.isValid())
return;
QByteArray payload = (power ? QByteArray::fromHex("01") : QByteArray::fromHex("00"));
m_humidityService->writeCharacteristic(m_humidityConfigurationCharacteristic, payload);
}
void SensorTag::setPressureSensorPower(bool power)
{
if (!m_pressureService || !m_pressureConfigurationCharacteristic.isValid())
return;
QByteArray payload = (power ? QByteArray::fromHex("01") : QByteArray::fromHex("00"));
m_pressureService->writeCharacteristic(m_pressureConfigurationCharacteristic, payload);
}
void SensorTag::setOpticalSensorPower(bool power)
{
if (!m_opticalService || !m_opticalConfigurationCharacteristic.isValid())
return;
QByteArray payload = (power ? QByteArray::fromHex("01") : QByteArray::fromHex("00"));
m_opticalService->writeCharacteristic(m_opticalConfigurationCharacteristic, payload);
}
void SensorTag::onConnectedChanged(const bool &connected)
{
qCDebug(dcMultiSensor()) << "Sensor" << m_bluetoothDevice->name() << m_bluetoothDevice->address().toString() << (connected ? "connected" : "disconnected");
m_device->setStateValue(sensortagConnectedStateTypeId, connected);
m_device->setStateValue(sensorTagConnectedStateTypeId, connected);
if (!connected) {
// Clean up services
m_infraredService->deleteLater();
m_buttonService->deleteLater();
m_temperatureService->deleteLater();
m_humidityService->deleteLater();
m_pressureService->deleteLater();
m_opticalService->deleteLater();
m_keyService->deleteLater();
m_movementService->deleteLater();
m_ioService->deleteLater();
m_infraredService = nullptr;
m_buttonService = nullptr;
m_temperatureService = nullptr;
m_humidityService = nullptr;
m_pressureService = nullptr;
}
m_opticalService = nullptr;
m_keyService = nullptr;
m_movementService = nullptr;
m_ioService = nullptr;
m_dataProcessor->reset();
}
}
void SensorTag::onServiceDiscoveryFinished()
{
if (!m_bluetoothDevice->serviceUuids().contains(infraredServiceUuid)) {
qCWarning(dcMultiSensor()) << "Could not find infrared service";
return;
foreach (const QBluetoothUuid serviceUuid, m_bluetoothDevice->serviceUuids()) {
qCDebug(dcMultiSensor()) << "-->" << serviceUuid;
}
if (!m_bluetoothDevice->serviceUuids().contains(accelerometerServiceUuid)) {
qCWarning(dcMultiSensor()) << "Could not find accelereometer service";
if (!m_bluetoothDevice->serviceUuids().contains(temperatureServiceUuid)) {
qCWarning(dcMultiSensor()) << "Could not find temperature service";
m_bluetoothDevice->disconnectDevice();
return;
}
if (!m_bluetoothDevice->serviceUuids().contains(humidityServiceUuid)) {
qCWarning(dcMultiSensor()) << "Could not find humidity service";
return;
}
if (!m_bluetoothDevice->serviceUuids().contains(magnetometerServiceUuid)) {
qCWarning(dcMultiSensor()) << "Could not find magnetometer service";
m_bluetoothDevice->disconnectDevice();
return;
}
if (!m_bluetoothDevice->serviceUuids().contains(pressureServiceUuid)) {
qCWarning(dcMultiSensor()) << "Could not find pressure service";
m_bluetoothDevice->disconnectDevice();
return;
}
if (!m_bluetoothDevice->serviceUuids().contains(gyroscopeServiceUuid)) {
qCWarning(dcMultiSensor()) << "Could not find magnetometer service";
if (!m_bluetoothDevice->serviceUuids().contains(opticalServiceUuid)) {
qCWarning(dcMultiSensor()) << "Could not find optical service";
m_bluetoothDevice->disconnectDevice();
return;
}
if (!m_bluetoothDevice->serviceUuids().contains(keyServiceUuid)) {
qCWarning(dcMultiSensor()) << "Could not find key service";
m_bluetoothDevice->disconnectDevice();
return;
}
if (!m_bluetoothDevice->serviceUuids().contains(movementServiceUuid)) {
qCWarning(dcMultiSensor()) << "Could not find movement service";
m_bluetoothDevice->disconnectDevice();
return;
}
if (!m_bluetoothDevice->serviceUuids().contains(ioServiceUuid)) {
qCWarning(dcMultiSensor()) << "Could not find IO service";
m_bluetoothDevice->disconnectDevice();
return;
}
// IR Temperature
if (!m_infraredService) {
m_infraredService = m_bluetoothDevice->controller()->createServiceObject(infraredServiceUuid, this);
if (!m_infraredService) {
qCWarning(dcMultiSensor()) << "Could not create infrared service.";
if (!m_temperatureService) {
m_temperatureService = m_bluetoothDevice->controller()->createServiceObject(temperatureServiceUuid, this);
if (!m_temperatureService) {
qCWarning(dcMultiSensor()) << "Could not create temperature service.";
m_bluetoothDevice->disconnectDevice();
return;
}
connect(m_infraredService, &QLowEnergyService::stateChanged, this, &SensorTag::onInfraredServiceStateChanged);
connect(m_infraredService, &QLowEnergyService::characteristicChanged, this, &SensorTag::onInfraredServiceCharacteristicChanged);
connect(m_temperatureService, &QLowEnergyService::stateChanged, this, &SensorTag::onTemperatureServiceStateChanged);
connect(m_temperatureService, &QLowEnergyService::characteristicChanged, this, &SensorTag::onTemperatureServiceCharacteristicChanged);
if (m_infraredService->state() == QLowEnergyService::DiscoveryRequired) {
m_infraredService->discoverDetails();
}
}
// Buttons
if (!m_buttonService) {
m_buttonService = m_bluetoothDevice->controller()->createServiceObject(buttonServiceUuid, this);
if (!m_buttonService) {
qCWarning(dcMultiSensor()) << "Could not create button service.";
return;
}
connect(m_buttonService, &QLowEnergyService::stateChanged, this, &SensorTag::onButtonServiceStateChanged);
connect(m_buttonService, &QLowEnergyService::characteristicChanged, this, &SensorTag::onButtonServiceCharacteristicChanged);
if (m_buttonService->state() == QLowEnergyService::DiscoveryRequired) {
m_buttonService->discoverDetails();
if (m_temperatureService->state() == QLowEnergyService::DiscoveryRequired) {
m_temperatureService->discoverDetails();
}
}
@ -133,6 +454,7 @@ void SensorTag::onServiceDiscoveryFinished()
m_humidityService = m_bluetoothDevice->controller()->createServiceObject(humidityServiceUuid, this);
if (!m_humidityService) {
qCWarning(dcMultiSensor()) << "Could not create humidity service.";
m_bluetoothDevice->disconnectDevice();
return;
}
@ -148,6 +470,7 @@ void SensorTag::onServiceDiscoveryFinished()
m_pressureService = m_bluetoothDevice->controller()->createServiceObject(pressureServiceUuid, this);
if (!m_pressureService) {
qCWarning(dcMultiSensor()) << "Could not create pressure service.";
m_bluetoothDevice->disconnectDevice();
return;
}
@ -157,17 +480,91 @@ void SensorTag::onServiceDiscoveryFinished()
m_pressureService->discoverDetails();
}
}
// Optical
if (!m_opticalService) {
m_opticalService = m_bluetoothDevice->controller()->createServiceObject(opticalServiceUuid, this);
if (!m_opticalService) {
qCWarning(dcMultiSensor()) << "Could not create optical service.";
m_bluetoothDevice->disconnectDevice();
return;
}
connect(m_opticalService, &QLowEnergyService::stateChanged, this, &SensorTag::onOpticalServiceStateChanged);
connect(m_opticalService, &QLowEnergyService::characteristicChanged, this, &SensorTag::onOpticalServiceCharacteristicChanged);
if (m_opticalService->state() == QLowEnergyService::DiscoveryRequired) {
m_opticalService->discoverDetails();
}
}
// Key
if (!m_keyService) {
m_keyService = m_bluetoothDevice->controller()->createServiceObject(keyServiceUuid, this);
if (!m_keyService) {
qCWarning(dcMultiSensor()) << "Could not create key service.";
m_bluetoothDevice->disconnectDevice();
return;
}
connect(m_keyService, &QLowEnergyService::stateChanged, this, &SensorTag::onKeyServiceStateChanged);
connect(m_keyService, &QLowEnergyService::characteristicChanged, this, &SensorTag::onKeyServiceCharacteristicChanged);
if (m_keyService->state() == QLowEnergyService::DiscoveryRequired) {
m_keyService->discoverDetails();
}
}
// Movement
if (!m_movementService) {
m_movementService = m_bluetoothDevice->controller()->createServiceObject(movementServiceUuid, this);
if (!m_movementService) {
qCWarning(dcMultiSensor()) << "Could not create movement service.";
m_bluetoothDevice->disconnectDevice();
return;
}
connect(m_movementService, &QLowEnergyService::stateChanged, this, &SensorTag::onMovementServiceStateChanged);
connect(m_movementService, &QLowEnergyService::characteristicChanged, this, &SensorTag::onMovementServiceCharacteristicChanged);
if (m_movementService->state() == QLowEnergyService::DiscoveryRequired) {
m_movementService->discoverDetails();
}
}
// IO
if (!m_ioService) {
m_ioService = m_bluetoothDevice->controller()->createServiceObject(ioServiceUuid, this);
if (!m_ioService) {
qCWarning(dcMultiSensor()) << "Could not create IO service.";
m_bluetoothDevice->disconnectDevice();
return;
}
connect(m_ioService, &QLowEnergyService::stateChanged, this, &SensorTag::onIoServiceStateChanged);
connect(m_ioService, &QLowEnergyService::characteristicChanged, this, &SensorTag::onIoServiceCharacteristicChanged);
if (m_ioService->state() == QLowEnergyService::DiscoveryRequired) {
m_ioService->discoverDetails();
}
}
}
void SensorTag::onInfraredServiceStateChanged(const QLowEnergyService::ServiceState &state)
void SensorTag::onBuzzerImpulseTimeout()
{
setBuzzerPower(false);
}
void SensorTag::onTemperatureServiceStateChanged(const QLowEnergyService::ServiceState &state)
{
// Only continue if discovered
if (state != QLowEnergyService::ServiceDiscovered)
return;
qCDebug(dcMultiSensor()) << "Infrared sensor service discovered.";
qCDebug(dcMultiSensor()) << "Temperature sensor service discovered.";
foreach (const QLowEnergyCharacteristic &characteristic, m_infraredService->characteristics()) {
foreach (const QLowEnergyCharacteristic &characteristic, m_temperatureService->characteristics()) {
qCDebug(dcMultiSensor()) << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value();
foreach (const QLowEnergyDescriptor &desciptor, characteristic.descriptors()) {
qCDebug(dcMultiSensor()) << " -->" << desciptor.name() << desciptor.uuid().toString() << desciptor.value();
@ -175,66 +572,44 @@ void SensorTag::onInfraredServiceStateChanged(const QLowEnergyService::ServiceSt
}
// Data characteristic
m_infraredDataCharacteristic = m_infraredService->characteristic(QBluetoothUuid(QUuid("f000aa01-0451-4000-b000-000000000000")));
if (!m_infraredDataCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid infrared data characteristic.";
m_temperatureDataCharacteristic = m_temperatureService->characteristic(QBluetoothUuid(QUuid("f000aa01-0451-4000-b000-000000000000")));
if (!m_temperatureDataCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid temperature data characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
}
// Enable notifications
QLowEnergyDescriptor notificationDescriptor = m_infraredDataCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_infraredService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
QLowEnergyDescriptor notificationDescriptor = m_temperatureDataCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_temperatureService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
// Config characteristic
m_infraredConfigCharacteristic = m_infraredService->characteristic(QBluetoothUuid(QUuid("f000aa02-0451-4000-b000-000000000000")));
if (!m_infraredConfigCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid infrared configuration characteristic.";
}
// Enable measuring
m_infraredService->writeCharacteristic(m_infraredConfigCharacteristic, QByteArray::fromHex("01"));
}
void SensorTag::onInfraredServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
if (characteristic == m_infraredDataCharacteristic) {
updateInfraredValue(value);
// FIXME: Disable measuring
// m_infraredService->writeCharacteristic(m_infraredConfigCharacteristic, QByteArray::fromHex("00"));
}
}
void SensorTag::onButtonServiceStateChanged(const QLowEnergyService::ServiceState &state)
{
// Only continue if discovered
if (state != QLowEnergyService::ServiceDiscovered)
m_temperatureConfigurationCharacteristic = m_temperatureService->characteristic(temperatureConfigurationCharacteristicUuid);
if (!m_temperatureConfigurationCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid temperature configuration characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
qCDebug(dcMultiSensor()) << "Button sensor service discovered.";
foreach (const QLowEnergyCharacteristic &characteristic, m_buttonService->characteristics()) {
qCDebug(dcMultiSensor()) << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value();
foreach (const QLowEnergyDescriptor &desciptor, characteristic.descriptors()) {
qCDebug(dcMultiSensor()) << " -->" << desciptor.name() << desciptor.uuid().toString() << desciptor.value();
}
}
// Data characteristic
m_buttonCharacteristic = m_buttonService->characteristic(QBluetoothUuid(QUuid("0000ffe1-0000-1000-8000-00805f9b34fb")));
if (!m_buttonCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid button data characteristic.";
// Period characteristic
m_temperaturePeriodCharacteristic = m_temperatureService->characteristic(temperaturePeriodCharacteristicUuid);
if (!m_temperaturePeriodCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid temperature period characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
}
// Enable notifications
QLowEnergyDescriptor notificationDescriptor = m_buttonCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_buttonService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
configurePeriod(m_temperatureService, m_temperaturePeriodCharacteristic, m_temperaturePeriod);
// Enable/disable measuring
setTemperatureSensorPower(m_temperatureEnabled);
}
void SensorTag::onButtonServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
void SensorTag::onTemperatureServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
if (characteristic == m_buttonCharacteristic) {
updateButtonValue(value);
if (characteristic == m_temperatureDataCharacteristic) {
m_dataProcessor->processTemperatureData(value);
}
}
@ -254,9 +629,11 @@ void SensorTag::onHumidityServiceStateChanged(const QLowEnergyService::ServiceSt
}
// Data characteristic
m_humidityDataCharacteristic = m_humidityService->characteristic(QBluetoothUuid(QUuid("f000aa21-0451-4000-b000-000000000000")));
m_humidityDataCharacteristic = m_humidityService->characteristic(humidityDataCharacteristicUuid);
if (!m_humidityDataCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid humidity data characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
}
// Enable notifications
@ -264,21 +641,31 @@ void SensorTag::onHumidityServiceStateChanged(const QLowEnergyService::ServiceSt
m_humidityService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
// Config characteristic
m_humidityConfigCharacteristic = m_humidityService->characteristic(QBluetoothUuid(QUuid("f000aa22-0451-4000-b000-000000000000")));
if (!m_humidityConfigCharacteristic.isValid()) {
m_humidityConfigurationCharacteristic = m_humidityService->characteristic(humidityConfigurationCharacteristicUuid);
if (!m_humidityConfigurationCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid humidity configuration characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
}
// Period characteristic
m_humidityPeriodCharacteristic = m_humidityService->characteristic(humidityPeriodCharacteristicUuid);
if (!m_humidityPeriodCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid humidity period characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
}
configurePeriod(m_humidityService, m_humidityPeriodCharacteristic, m_humidityPeriod);
// Enable measuring
m_humidityService->writeCharacteristic(m_humidityConfigCharacteristic, QByteArray::fromHex("01"));
m_humidityService->writeCharacteristic(m_humidityConfigurationCharacteristic, QByteArray::fromHex("01"));
}
void SensorTag::onHumidityServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
if (characteristic == m_humidityDataCharacteristic) {
updateHumidityValue(value);
// FIXME: Disable measuring
// m_humidityService->writeCharacteristic(m_humidityConfigCharacteristic, QByteArray::fromHex("00"));
m_dataProcessor->processHumidityData(value);
}
}
@ -298,9 +685,11 @@ void SensorTag::onPressureServiceStateChanged(const QLowEnergyService::ServiceSt
}
// Data characteristic
m_pressureDataCharacteristic = m_pressureService->characteristic(QBluetoothUuid(QUuid("f000aa41-0451-4000-b000-000000000000")));
m_pressureDataCharacteristic = m_pressureService->characteristic(pressureDataCharacteristicUuid);
if (!m_pressureDataCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid pressure data characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
}
// Enable notifications
@ -308,36 +697,216 @@ void SensorTag::onPressureServiceStateChanged(const QLowEnergyService::ServiceSt
m_pressureService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
// Config characteristic
m_pressureConfigCharacteristic = m_pressureService->characteristic(QBluetoothUuid(QUuid("f000aa42-0451-4000-b000-000000000000")));
if (!m_pressureConfigCharacteristic.isValid()) {
m_pressureConfigurationCharacteristic = m_pressureService->characteristic(pressureConfigurationCharacteristicUuid);
if (!m_pressureConfigurationCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid pressure configuration characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
}
// Period characteristic
m_pressurePeriodCharacteristic = m_pressureService->characteristic(pressurePeriodCharacteristicUuid);
if (!m_pressurePeriodCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid pressure period characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
}
configurePeriod(m_pressureService, m_pressurePeriodCharacteristic, m_pressurePeriod);
// Enable measuring
m_pressureService->writeCharacteristic(m_pressureConfigCharacteristic, QByteArray::fromHex("01"));
m_pressureService->writeCharacteristic(m_pressureConfigurationCharacteristic, QByteArray::fromHex("01"));
}
void SensorTag::onPressureServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
if (characteristic == m_pressureDataCharacteristic) {
updatePressureValue(value);
// FIXME: Disable measuring
// m_pressureService->writeCharacteristic(m_pressureConfigCharacteristic, QByteArray::fromHex("00"));
m_dataProcessor->processPressureData(value);
}
}
void SensorTag::measure()
void SensorTag::onOpticalServiceStateChanged(const QLowEnergyService::ServiceState &state)
{
if (!m_bluetoothDevice->connected())
// Only continue if discovered
if (state != QLowEnergyService::ServiceDiscovered)
return;
// TODO: measure using plugintimer to save energy
qCDebug(dcMultiSensor()) << "Optical sensor service discovered.";
// qCDebug(dcMultiSensor()) << "Measure data" << m_bluetoothDevice->name() << m_bluetoothDevice->address().toString();
foreach (const QLowEnergyCharacteristic &characteristic, m_pressureService->characteristics()) {
qCDebug(dcMultiSensor()) << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value();
foreach (const QLowEnergyDescriptor &desciptor, characteristic.descriptors()) {
qCDebug(dcMultiSensor()) << " -->" << desciptor.name() << desciptor.uuid().toString() << desciptor.value();
}
}
// m_infraredService->writeCharacteristic(m_infraredConfigCharacteristic, QByteArray::fromHex("01"));
// m_humidityService->writeCharacteristic(m_humidityConfigCharacteristic, QByteArray::fromHex("01"));
// m_pressureService->writeCharacteristic(m_pressureConfigCharacteristic, QByteArray::fromHex("01"));
// Data characteristic
m_opticalDataCharacteristic = m_opticalService->characteristic(opticalDataCharacteristicUuid);
if (!m_opticalDataCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid optical data characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
}
// Enable notifications
QLowEnergyDescriptor notificationDescriptor = m_opticalDataCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_opticalService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
// Config characteristic
m_opticalConfigurationCharacteristic = m_opticalService->characteristic(opticalConfigurationCharacteristicUuid);
if (!m_opticalConfigurationCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid optical configuration characteristic.";
m_bluetoothDevice->disconnectDevice();
}
// Period characteristic
m_opticalPeriodCharacteristic = m_opticalService->characteristic(opticalPeriodCharacteristicUuid);
if (!m_opticalPeriodCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid optical period characteristic.";
m_bluetoothDevice->disconnectDevice();
}
// Set measurement period
configurePeriod(m_opticalService, m_opticalPeriodCharacteristic, m_opticalPeriod);
// Enable measuring
m_opticalService->writeCharacteristic(m_opticalConfigurationCharacteristic, QByteArray::fromHex("01"));
}
void SensorTag::onOpticalServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
if (characteristic == m_opticalDataCharacteristic) {
m_dataProcessor->processOpticalData(value);
}
}
void SensorTag::onKeyServiceStateChanged(const QLowEnergyService::ServiceState &state)
{
// Only continue if discovered
if (state != QLowEnergyService::ServiceDiscovered)
return;
qCDebug(dcMultiSensor()) << "Key service discovered.";
foreach (const QLowEnergyCharacteristic &characteristic, m_keyService->characteristics()) {
qCDebug(dcMultiSensor()) << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value();
foreach (const QLowEnergyDescriptor &desciptor, characteristic.descriptors()) {
qCDebug(dcMultiSensor()) << " -->" << desciptor.name() << desciptor.uuid().toString() << desciptor.value();
}
}
// Data characteristic
m_keyDataCharacteristic = m_keyService->characteristic(keyDataCharacteristicUuid);
if (!m_keyDataCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid button data characteristic.";
m_bluetoothDevice->disconnectDevice();
}
// Enable notifications
QLowEnergyDescriptor notificationDescriptor = m_keyDataCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_keyService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
}
void SensorTag::onKeyServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
if (characteristic == m_keyDataCharacteristic) {
m_dataProcessor->processKeyData(value);
}
}
void SensorTag::onMovementServiceStateChanged(const QLowEnergyService::ServiceState &state)
{
// Only continue if discovered
if (state != QLowEnergyService::ServiceDiscovered)
return;
qCDebug(dcMultiSensor()) << "Movement sensor service discovered.";
foreach (const QLowEnergyCharacteristic &characteristic, m_pressureService->characteristics()) {
qCDebug(dcMultiSensor()) << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value();
foreach (const QLowEnergyDescriptor &desciptor, characteristic.descriptors()) {
qCDebug(dcMultiSensor()) << " -->" << desciptor.name() << desciptor.uuid().toString() << desciptor.value();
}
}
// Data characteristic
m_movementDataCharacteristic = m_movementService->characteristic(movementDataCharacteristicUuid);
if (!m_movementDataCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid movement data characteristic.";
m_bluetoothDevice->disconnectDevice();
}
// Enable notifications
QLowEnergyDescriptor notificationDescriptor = m_movementDataCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_movementService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
// Config characteristic
m_movementConfigurationCharacteristic = m_movementService->characteristic(movementConfigurationCharacteristicUuid);
if (!m_movementConfigurationCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid movement configuration characteristic.";
m_bluetoothDevice->disconnectDevice();
}
// Period characteristic
m_movementPeriodCharacteristic = m_movementService->characteristic(movementPeriodCharacteristicUuid);
if (!m_movementPeriodCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid movement period characteristic.";
m_bluetoothDevice->disconnectDevice();
}
// Set measurement period
configurePeriod(m_movementService, m_movementPeriodCharacteristic, m_movementPeriod);
configureMovement();
// Enable measuring
m_movementService->writeCharacteristic(m_movementConfigurationCharacteristic, QByteArray::fromHex("01"));
}
void SensorTag::onMovementServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
if (characteristic == m_movementDataCharacteristic) {
m_dataProcessor->processMovementData(value);
}
}
void SensorTag::onIoServiceStateChanged(const QLowEnergyService::ServiceState &state)
{
// Only continue if discovered
if (state != QLowEnergyService::ServiceDiscovered)
return;
qCDebug(dcMultiSensor()) << "IO service discovered.";
foreach (const QLowEnergyCharacteristic &characteristic, m_pressureService->characteristics()) {
qCDebug(dcMultiSensor()) << " -->" << characteristic.name() << characteristic.uuid().toString() << characteristic.value();
foreach (const QLowEnergyDescriptor &desciptor, characteristic.descriptors()) {
qCDebug(dcMultiSensor()) << " -->" << desciptor.name() << desciptor.uuid().toString() << desciptor.value();
}
}
// Data characteristic
m_ioDataCharacteristic = m_ioService->characteristic(ioDataCharacteristicUuid);
if (!m_ioDataCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid IO data characteristic.";
m_bluetoothDevice->disconnectDevice();
}
// Enable notifications
QLowEnergyDescriptor notificationDescriptor = m_ioDataCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_ioService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
// Config characteristic
m_ioConfigurationCharacteristic = m_ioService->characteristic(ioConfigurationCharacteristicUuid);
if (!m_ioConfigurationCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid IO configuration characteristic.";
m_bluetoothDevice->disconnectDevice();
}
configureIo();
configureSensorMode(SensorModeRemote);
configureIo();
}
void SensorTag::onIoServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
qCDebug(dcMultiSensor()) << characteristic.uuid().toString() << value.toHex();
}

View File

@ -1,3 +1,25 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015-2018 Simon Stuerz <simon.stuerz@guh.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef SENSORTAG_H
#define SENSORTAG_H
@ -5,72 +27,178 @@
#include "plugin/device.h"
#include "extern-plugininfo.h"
#include "sensordataprocessor.h"
#include "hardware/bluetoothlowenergy/bluetoothlowenergydevice.h"
static QBluetoothUuid infraredServiceUuid = QBluetoothUuid(QUuid("f000aa00-0451-4000-b000-000000000000"));
static QBluetoothUuid accelerometerServiceUuid = QBluetoothUuid(QUuid("f000aa10-0451-4000-b000-000000000000"));
static QBluetoothUuid humidityServiceUuid = QBluetoothUuid(QUuid("f000aa20-0451-4000-b000-000000000000"));
static QBluetoothUuid magnetometerServiceUuid = QBluetoothUuid(QUuid("f000aa30-0451-4000-b000-000000000000"));
static QBluetoothUuid pressureServiceUuid = QBluetoothUuid(QUuid("f000aa40-0451-4000-b000-000000000000"));
static QBluetoothUuid gyroscopeServiceUuid = QBluetoothUuid(QUuid("f000aa50-0451-4000-b000-000000000000"));
static QBluetoothUuid testServiceUuid = QBluetoothUuid(QUuid("f000aa60-0451-4000-b000-000000000000"));
static QBluetoothUuid otaServiceUuid = QBluetoothUuid(QUuid("f000aac0-0451-4000-b000-000000000000"));
static QBluetoothUuid buttonServiceUuid = QBluetoothUuid(QUuid("0000ffe0-0000-1000-8000-00805f9b34fb"));
// http://processors.wiki.ti.com/index.php/CC2650_SensorTag_User's_Guide
static QBluetoothUuid temperatureServiceUuid = QBluetoothUuid(QUuid("f000aa00-0451-4000-b000-000000000000"));
static QBluetoothUuid temperatureDataCharacteristicUuid = QBluetoothUuid(QUuid("f000aa01-0451-4000-b000-000000000000"));
static QBluetoothUuid temperatureConfigurationCharacteristicUuid = QBluetoothUuid(QUuid("f000aa02-0451-4000-b000-000000000000"));
static QBluetoothUuid temperaturePeriodCharacteristicUuid = QBluetoothUuid(QUuid("f000aa03-0451-4000-b000-000000000000"));
static QBluetoothUuid humidityServiceUuid = QBluetoothUuid(QUuid("f000aa20-0451-4000-b000-000000000000"));
static QBluetoothUuid humidityDataCharacteristicUuid = QBluetoothUuid(QUuid("f000aa21-0451-4000-b000-000000000000"));
static QBluetoothUuid humidityConfigurationCharacteristicUuid = QBluetoothUuid(QUuid("f000aa22-0451-4000-b000-000000000000"));
static QBluetoothUuid humidityPeriodCharacteristicUuid = QBluetoothUuid(QUuid("f000aa23-0451-4000-b000-000000000000"));
static QBluetoothUuid pressureServiceUuid = QBluetoothUuid(QUuid("f000aa40-0451-4000-b000-000000000000"));
static QBluetoothUuid pressureDataCharacteristicUuid = QBluetoothUuid(QUuid("f000aa41-0451-4000-b000-000000000000"));
static QBluetoothUuid pressureConfigurationCharacteristicUuid = QBluetoothUuid(QUuid("f000aa42-0451-4000-b000-000000000000"));
static QBluetoothUuid pressurePeriodCharacteristicUuid = QBluetoothUuid(QUuid("f000aa44-0451-4000-b000-000000000000"));
static QBluetoothUuid opticalServiceUuid = QBluetoothUuid(QUuid("f000aa70-0451-4000-b000-000000000000"));
static QBluetoothUuid opticalDataCharacteristicUuid = QBluetoothUuid(QUuid("f000aa71-0451-4000-b000-000000000000"));
static QBluetoothUuid opticalConfigurationCharacteristicUuid = QBluetoothUuid(QUuid("f000aa72-0451-4000-b000-000000000000"));
static QBluetoothUuid opticalPeriodCharacteristicUuid = QBluetoothUuid(QUuid("f000aa73-0451-4000-b000-000000000000"));
static QBluetoothUuid keyServiceUuid = QBluetoothUuid(QUuid("0000ffe0-0000-1000-8000-00805f9b34fb"));
static QBluetoothUuid keyDataCharacteristicUuid = QBluetoothUuid(QUuid("0000ffe1-0000-1000-8000-00805f9b34fb"));
static QBluetoothUuid ioServiceUuid = QBluetoothUuid(QUuid("f000aa64-0451-4000-b000-000000000000"));
static QBluetoothUuid ioDataCharacteristicUuid = QBluetoothUuid(QUuid("f000aa65-0451-4000-b000-000000000000"));
static QBluetoothUuid ioConfigurationCharacteristicUuid = QBluetoothUuid(QUuid("f000aa66-0451-4000-b000-000000000000"));
static QBluetoothUuid movementServiceUuid = QBluetoothUuid(QUuid("f000aa80-0451-4000-b000-000000000000"));
static QBluetoothUuid movementDataCharacteristicUuid = QBluetoothUuid(QUuid("f000aa81-0451-4000-b000-000000000000"));
static QBluetoothUuid movementConfigurationCharacteristicUuid = QBluetoothUuid(QUuid("f000aa82-0451-4000-b000-000000000000"));
static QBluetoothUuid movementPeriodCharacteristicUuid = QBluetoothUuid(QUuid("f000aa83-0451-4000-b000-000000000000"));
// Currently unused services
class SensorTag : public QObject
{
Q_OBJECT
public:
enum SensorAccelerometerRange {
SensorAccelerometerRange2G = 2,
SensorAccelerometerRange4G = 4,
SensorAccelerometerRange8G = 8,
SensorAccelerometerRange16G = 16
};
Q_ENUM(SensorAccelerometerRange)
enum SensorMode {
SensorModeLocal = 0,
SensorModeRemote = 1,
SensorModeTest = 2
};
Q_ENUM(SensorMode)
explicit SensorTag(Device *device, BluetoothLowEnergyDevice *bluetoothDevice, QObject *parent = nullptr);
Device *device();
BluetoothLowEnergyDevice *bluetoothDevice();
// Configurations
void setTemperatureSensorEnabled(bool enabled);
void setHumiditySensorEnabled(bool enabled);
void setPressureSensorEnabled(bool enabled);
void setOpticalSensorEnabled(bool enabled);
void setAccelerometerEnabled(bool enabled);
void setGyroscopeEnabled(bool enabled);
void setMagnetometerEnabled(bool enabled);
void setAccelerometerRange(const SensorAccelerometerRange &range);
void setMeasurementPeriod(int period);
void setMeasurementPeriodMovement(int period);
void setMovementSensitivity(int percentage);
// Actions
void setGreenLedPower(bool power);
void setRedLedPower(bool power);
void setBuzzerPower(bool power);
void buzzerImpulse();
private:
Device *m_device;
BluetoothLowEnergyDevice *m_bluetoothDevice;
// Services
QLowEnergyService *m_infraredService = nullptr;
QLowEnergyService *m_buttonService = nullptr;
QLowEnergyService *m_temperatureService = nullptr;
QLowEnergyService *m_humidityService = nullptr;
QLowEnergyService *m_pressureService = nullptr;
QLowEnergyService *m_accelerometerService = nullptr;
QLowEnergyService *m_magnetometerService = nullptr;
QLowEnergyService *m_gyroscopeService = nullptr;
QLowEnergyService *m_opticalService = nullptr;
QLowEnergyService *m_keyService = nullptr;
QLowEnergyService *m_movementService = nullptr;
QLowEnergyService *m_ioService = nullptr;
// Characteristics
QLowEnergyCharacteristic m_infraredDataCharacteristic;
QLowEnergyCharacteristic m_infraredConfigCharacteristic;
QLowEnergyCharacteristic m_buttonCharacteristic;
QLowEnergyCharacteristic m_temperatureDataCharacteristic;
QLowEnergyCharacteristic m_temperatureConfigurationCharacteristic;
QLowEnergyCharacteristic m_temperaturePeriodCharacteristic;
QLowEnergyCharacteristic m_humidityDataCharacteristic;
QLowEnergyCharacteristic m_humidityConfigCharacteristic;
QLowEnergyCharacteristic m_humidityConfigurationCharacteristic;
QLowEnergyCharacteristic m_humidityPeriodCharacteristic;
QLowEnergyCharacteristic m_pressureDataCharacteristic;
QLowEnergyCharacteristic m_pressureConfigCharacteristic;
QLowEnergyCharacteristic m_pressureConfigurationCharacteristic;
QLowEnergyCharacteristic m_pressurePeriodCharacteristic;
QLowEnergyCharacteristic m_opticalDataCharacteristic;
QLowEnergyCharacteristic m_opticalConfigurationCharacteristic;
QLowEnergyCharacteristic m_opticalPeriodCharacteristic;
void updateInfraredValue(const QByteArray &value);
void updateButtonValue(const QByteArray &value);
void updateHumidityValue(const QByteArray &value);
void updatePressureValue(const QByteArray &value);
QLowEnergyCharacteristic m_keyDataCharacteristic;
QLowEnergyCharacteristic m_movementDataCharacteristic;
QLowEnergyCharacteristic m_movementConfigurationCharacteristic;
QLowEnergyCharacteristic m_movementPeriodCharacteristic;
QLowEnergyCharacteristic m_ioDataCharacteristic;
QLowEnergyCharacteristic m_ioConfigurationCharacteristic;
// Measure periods
int m_temperaturePeriod = 2500;
int m_humidityPeriod = 2500;
int m_pressurePeriod = 2500;
int m_opticalPeriod = 2500;
int m_movementPeriod = 500;
double m_movementSensitivity = 0.5;
SensorAccelerometerRange m_accelerometerRange = SensorAccelerometerRange16G;
// States
bool m_greenLedEnabled = false;
bool m_redLedEnabled = false;
bool m_buzzerEnabled = false;
// Plugin configs
bool m_temperatureEnabled = true;
bool m_humidityEnabled = true;
bool m_pressureEnabled = true;
bool m_opticalEnabled = true;
bool m_accelerometerEnabled = true;
bool m_gyroscopeEnabled = false;
bool m_magnetometerEnabled = false;
SensorDataProcessor *m_dataProcessor = nullptr;
// Configuration methods
void configurePeriod(QLowEnergyService *serice, const QLowEnergyCharacteristic &characteristic, int measurementPeriod);
void configureMovement();
void configureSensorMode(const SensorMode &mode);
void configureIo();
void setTemperatureSensorPower(bool power);
void setHumiditySensorPower(bool power);
void setPressureSensorPower(bool power);
void setOpticalSensorPower(bool power);
signals:
void leftKeyPressed();
void rightKeyPressed();
void leftButtonPressedChanged(bool pressed);
void rightButtonPressedChanged(bool pressed);
void magnetDetectedChanged(bool detected);
private slots:
void onConnectedChanged(const bool &connected);
void onServiceDiscoveryFinished();
// Infrared sensor service
void onInfraredServiceStateChanged(const QLowEnergyService::ServiceState &state);
void onInfraredServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
void onBuzzerImpulseTimeout();
// Button service
void onButtonServiceStateChanged(const QLowEnergyService::ServiceState &state);
void onButtonServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
// Temperature sensor service
void onTemperatureServiceStateChanged(const QLowEnergyService::ServiceState &state);
void onTemperatureServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
// Humidity sensor service
void onHumidityServiceStateChanged(const QLowEnergyService::ServiceState &state);
@ -80,10 +208,21 @@ private slots:
void onPressureServiceStateChanged(const QLowEnergyService::ServiceState &state);
void onPressureServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
// Optical sensor service
void onOpticalServiceStateChanged(const QLowEnergyService::ServiceState &state);
void onOpticalServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
public slots:
void measure();
// Button service
void onKeyServiceStateChanged(const QLowEnergyService::ServiceState &state);
void onKeyServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
// Movement service
void onMovementServiceStateChanged(const QLowEnergyService::ServiceState &state);
void onMovementServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
// IO service
void onIoServiceStateChanged(const QLowEnergyService::ServiceState &state);
void onIoServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value);
};
#endif // SENSORTAG_H