Add first version of new sensor tag

This commit is contained in:
Simon Stürz 2018-02-22 23:24:43 +01:00
parent be1bc16479
commit 0479ecb0bb
5 changed files with 779 additions and 222 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,10 +52,15 @@ 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)
@ -89,8 +94,6 @@ DeviceManager::DeviceSetupStatus DevicePluginMultiSensor::setupDevice(Device *de
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();
@ -124,23 +127,13 @@ 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());

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. *
@ -41,6 +41,7 @@ class DevicePluginMultiSensor : public DevicePlugin
public:
explicit DevicePluginMultiSensor();
~DevicePluginMultiSensor();
void init() override;
DeviceManager::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
@ -48,17 +49,13 @@ public:
void deviceRemoved(Device *device) 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();
};

View File

@ -2,6 +2,47 @@
"displayName": "MultiSensor",
"name": "MultiSensor",
"id": "23bf0d8d-df7d-4bee-80ee-f015c5a7f52e",
"paramTypes": [
{
"id": "5786c91a-d94d-461a-8d22-f978dd1438ab",
"name": "accelerometerEnabled",
"displayName": "Accelerometer enabled",
"type": "bool",
"defaultValue": true
},
{
"id": "94517544-cb97-4816-8993-cb4cf2651a1e",
"name": "gyroscopeEnabled",
"displayName": "Gyroscope enabled",
"type": "bool",
"defaultValue": false
},
{
"id": "96aae111-b1c1-48a1-9b1f-b56efa546d0d",
"name": "magnetometerEnabled",
"displayName": "Magnetometer enabled",
"type": "bool",
"defaultValue": false
},
{
"id": "5237c89c-c21d-4d78-ac99-8be661b40da7",
"name": "measurementPeriodMovement",
"displayName": "Measurement period movement sensor",
"type": "int",
"minValue": 10,
"maxValue": 2500,
"defaultValue": 2000
},
{
"id": "c5308565-5dc9-409e-ae99-577c212c7a92",
"name": "measurementPeriod",
"displayName": "Measurement period for enviromental sensors",
"type": "int",
"minValue": 10,
"maxValue": 2500,
"defaultValue": 500
}
],
"vendors": [
{
"id": "2edf543e-dc2c-4693-bb0c-e76c0d305fad",
@ -9,12 +50,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": ["connectable", "humiditysensor", "temperaturesensor"],
"basicTags": [
"Device",
"Sensor"
@ -23,14 +64,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 +80,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 +95,79 @@
"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
}
]
}

View File

@ -1,6 +1,30 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 <QDataStream>
SensorTag::SensorTag(Device *device, BluetoothLowEnergyDevice *bluetoothDevice, QObject *parent) :
QObject(parent),
m_device(device),
@ -20,28 +44,212 @@ BluetoothLowEnergyDevice *SensorTag::bluetoothDevice()
return m_bluetoothDevice;
}
void SensorTag::updateInfraredValue(const QByteArray &value)
void SensorTag::setAccelerometerEnabled(bool enabled)
{
qCDebug(dcMultiSensor()) << "Infrared value" << value;
m_accelerometerEnabled = enabled;
}
void SensorTag::updateButtonValue(const QByteArray &value)
void SensorTag::configurePeriod(QLowEnergyService *serice, const QLowEnergyCharacteristic &characteristic, int measurementPeriod)
{
const quint8 *data = reinterpret_cast<const quint8 *>(value.constData());
if (*data & 1)
emit leftKeyPressed();
if (*data & 2)
emit rightKeyPressed();
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::updateHumidityValue(const QByteArray &value)
void SensorTag::configureMovement(bool gyroscopeEnabled, bool accelerometerEnabled, bool magnetometerEnabled, bool wakeOnMotion)
{
qCDebug(dcMultiSensor()) << "Humidity value" << value;
if (!m_movementService || !m_movementConfigurationCharacteristic.isValid())
return;
quint16 configuration = 0;
if (gyroscopeEnabled) {
configuration |= (1 << 0); // enable x-axis
configuration |= (1 << 1); // enable y-axis
configuration |= (1 << 2); // enable z-axis
}
if (accelerometerEnabled) {
configuration |= (1 << 3); // enable x-axis
configuration |= (1 << 4); // enable y-axis
configuration |= (1 << 5); // enable z-axis
}
if (magnetometerEnabled) {
configuration |= (1 << 6); // enable all axis
}
if (wakeOnMotion) {
configuration |= (1 << 8); // enable
}
// Accelerometer 2 Bit ( 0 = 2G, 1 = 4G, 2 = 8G, 3 = 16G)
// Default 0
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::BigEndian);
stream << configuration;
qCDebug(dcMultiSensor()) << "Configure movement sensor" << data.toHex();
m_movementService->writeCharacteristic(m_movementConfigurationCharacteristic, data);
}
void SensorTag::updatePressureValue(const QByteArray &value)
void SensorTag::processTemperatureData(const QByteArray &data)
{
qCDebug(dcMultiSensor()) << "Pressure value" << value;
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 ;
float scaleFactor = 0.03125;
float objectTemperature = static_cast<float>(rawObjectTemperature) / 4 * scaleFactor;
float ambientTemperature = static_cast<float>(rawAmbientTemperature) / 4 * scaleFactor;
//qCDebug(dcMultiSensor()) << "Temperature value" << data.toHex();
//qCDebug(dcMultiSensor()) << "Object temperature" << roundValue(objectTemperature) << "°C";
//qCDebug(dcMultiSensor()) << "Ambient temperature" << roundValue(ambientTemperature) << "°C";
m_device->setStateValue(sensortagObjectTemperatureStateTypeId, roundValue(objectTemperature));
m_device->setStateValue(sensortagTemperatureStateTypeId, roundValue(ambientTemperature));
}
void SensorTag::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 SensorTag::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 ;
//double humidityTemperature = (rawHumidityTemperature / 65536.0 * 165.0) - 40;
double humidity = rawHumidity / 65536.0 * 100.0;
//qCDebug(dcMultiSensor()) << "Humidity" << humidity << "%" << humidityTemperature << "°C";
m_device->setStateValue(sensortagHumidityStateTypeId, roundValue(humidity));
}
void SensorTag::processPressureData(const QByteArray &data)
{
Q_ASSERT(data.count() == 6);
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));
//qCDebug(dcMultiSensor()) << "Pressure:" << roundValue(rawPressure / 100.0) << "mBar";
m_device->setStateValue(sensortagPressureStateTypeId, roundValue(rawPressure / 100.0));
}
void SensorTag::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;
device()->setStateValue(sensortagLightIntensityStateTypeId, roundValue(lux));
}
void SensorTag::processMovementData(const QByteArray &data)
{
qCDebug(dcMultiSensor()) << "Movement value" << data.toHex();
QByteArray payload(data);
QDataStream stream(&payload, QIODevice::ReadOnly);
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, unit deg/s, range -250, +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);
qCDebug(dcMultiSensor()) << "Gyroscope x:" << gyroX << " y:" << gyroY << " z:" << gyroZ;
}
void SensorTag::setLeftButtonPressed(bool pressed)
{
if (m_leftButtonPressed == pressed)
return;
qCDebug(dcMultiSensor()) << "Left button" << (pressed ? "pressed" : "released");
m_leftButtonPressed = pressed;
emit leftButtonPressedChainged(m_leftButtonPressed);
m_device->setStateValue(sensortagLeftButtonPressedStateTypeId, m_leftButtonPressed);
}
void SensorTag::setRightButtonPressed(bool pressed)
{
if (m_rightButtonPressed == pressed)
return;
qCDebug(dcMultiSensor()) << "Right button" << (pressed ? "pressed" : "released");
m_rightButtonPressed = pressed;
emit rightButtonPressedChainged(m_rightButtonPressed);
m_device->setStateValue(sensortagRightButtonPressedStateTypeId, m_rightButtonPressed);
}
void SensorTag::setMagnetDetected(bool detected)
{
if (m_magnetDetected == detected)
return;
qCDebug(dcMultiSensor()) << "Magnet detector" << (detected ? "active" : "inactive");
m_magnetDetected = detected;
emit magnetDetectedChainged(m_magnetDetected);
m_device->setStateValue(sensortagMagnetDetectedStateTypeId, m_magnetDetected);
}
bool SensorTag::testBitUint8(quint8 value, int bitPosition)
{
return (((value)>> (bitPosition)) & 1);
}
double SensorTag::roundValue(float value)
{
int tmpValue = static_cast<int>(value * 10);
return static_cast<double>(tmpValue) / 10.0;
}
void SensorTag::onConnectedChanged(const bool &connected)
@ -51,80 +259,79 @@ void SensorTag::onConnectedChanged(const bool &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_infraredService = nullptr;
m_buttonService = nullptr;
m_temperatureService = nullptr;
m_humidityService = nullptr;
m_pressureService = nullptr;
m_opticalService = nullptr;
m_keyService = nullptr;
m_movementService = nullptr;
}
}
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;
}
// 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 +340,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 +356,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 +366,69 @@ 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();
}
}
}
void SensorTag::onInfraredServiceStateChanged(const QLowEnergyService::ServiceState &state)
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 +436,47 @@ 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.";
m_temperatureConfigurationCharacteristic = m_temperatureService->characteristic(temperatureConfigurationCharacteristicUuid);
if (!m_temperatureConfigurationCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid temperature configuration characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
}
// Period characteristic
m_temperaturePeriodCharacteristic = m_temperatureService->characteristic(temperaturePeriodCharacteristicUuid);
if (!m_temperaturePeriodCharacteristic.isValid()) {
qCWarning(dcMultiSensor()) << "Invalid temperature period characteristic.";
m_bluetoothDevice->disconnectDevice();
return;
}
configurePeriod(m_temperatureService, m_temperaturePeriodCharacteristic, m_temperaturePeriod);
// Enable measuring
m_infraredService->writeCharacteristic(m_infraredConfigCharacteristic, QByteArray::fromHex("01"));
m_temperatureService->writeCharacteristic(m_temperatureConfigurationCharacteristic, QByteArray::fromHex("01"));
}
void SensorTag::onInfraredServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
void SensorTag::onTemperatureServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
if (characteristic == m_infraredDataCharacteristic) {
updateInfraredValue(value);
if (characteristic == m_temperatureDataCharacteristic) {
processTemperatureData(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)
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.";
}
// Enable notifications
QLowEnergyDescriptor notificationDescriptor = m_buttonCharacteristic.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
m_buttonService->writeDescriptor(notificationDescriptor, QByteArray::fromHex("0100"));
}
void SensorTag::onButtonServiceCharacteristicChanged(const QLowEnergyCharacteristic &characteristic, const QByteArray &value)
{
if (characteristic == m_buttonCharacteristic) {
updateButtonValue(value);
// m_temperatureService->writeCharacteristic(m_temperatureConfigCharacteristic, QByteArray::fromHex("00"));
}
}
@ -254,9 +496,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,19 +508,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);
processHumidityData(value);
// FIXME: Disable measuring
// m_humidityService->writeCharacteristic(m_humidityConfigCharacteristic, QByteArray::fromHex("00"));
}
@ -298,9 +554,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 +566,179 @@ 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);
processPressureData(value);
// FIXME: Disable measuring
// m_pressureService->writeCharacteristic(m_pressureConfigCharacteristic, QByteArray::fromHex("00"));
}
}
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) {
processOpticalData(value);
// FIXME: Disable measuring
// m_opticalService->writeCharacteristic(m_pressureopticalCharacteristic, QByteArray::fromHex("00"));
}
}
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) {
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) {
processMovementData(value);
}
}

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
@ -7,17 +29,40 @@
#include "extern-plugininfo.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
{
@ -28,49 +73,93 @@ public:
Device *device();
BluetoothLowEnergyDevice *bluetoothDevice();
void setAccelerometerEnabled(bool enabled);
void setGyroscopeEnabled(bool enabled);
void setMagnetometerEnabled(bool enabled);
void setMeasurementPeriod(int period);
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;
// 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;
// Measure periods
int m_temperaturePeriod = 2500;
int m_humidityPeriod = 2500;
int m_pressurePeriod = 2500;
int m_opticalPeriod = 2500;
int m_movementPeriod = 500;
bool m_leftButtonPressed = false;
bool m_rightButtonPressed = false;
bool m_magnetDetected = false;
// Plugin configs
bool m_accelerometerEnabled = true;
bool m_gyroscopeEnabled = false;
bool m_magnetometerEnabled = false;
void configurePeriod(QLowEnergyService *serice, const QLowEnergyCharacteristic &characteristic, int measurementPeriod);
void configureMovement(bool gyroscopeEnabled = false, bool accelerometerEnabled = true, bool magnetometerEnabled = true, bool wakeOnMotion = true);
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);
// Set methods
void setLeftButtonPressed(bool pressed);
void setRightButtonPressed(bool pressed);
void setMagnetDetected(bool detected);
// Helper
bool testBitUint8(quint8 value, int bitPosition);
double roundValue(float value);
signals:
void leftKeyPressed();
void rightKeyPressed();
void leftButtonPressedChainged(bool pressed);
void rightButtonPressedChainged(bool pressed);
void magnetDetectedChainged(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);
// 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,9 +169,17 @@ 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);
};