mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-07-18 00:43:48 +02:00
Merge remote-tracking branch 'origin/texas-instruments-sensortag'
This commit is contained in:
commit
0dde37ee41
@ -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 ¶ms)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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 ¶ms) 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
|
||||
|
||||
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
15
multisensor/multisensor.plot
Normal file
15
multisensor/multisensor.plot
Normal 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"
|
||||
|
||||
@ -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
|
||||
|
||||
329
multisensor/sensordataprocessor.cpp
Normal file
329
multisensor/sensordataprocessor.cpp
Normal 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;
|
||||
}
|
||||
93
multisensor/sensordataprocessor.h
Normal file
93
multisensor/sensordataprocessor.h
Normal 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
|
||||
178
multisensor/sensorfilter.cpp
Normal file
178
multisensor/sensorfilter.cpp
Normal 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();
|
||||
}
|
||||
81
multisensor/sensorfilter.h
Normal file
81
multisensor/sensorfilter.h
Normal 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
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user