diff options
author | Otto Ryynänen <otto.ryynanen@qt.io> | 2017-01-30 16:30:13 +0200 |
---|---|---|
committer | Kari Hautamäki <kari.hautamaki@qt.io> | 2017-01-31 11:15:58 +0000 |
commit | 4a7c0e5841b2bb69ddaef2c9620c443934d194ee (patch) | |
tree | 0997ae3fdb9de74ace3d140724b96fe1fdde386d /tradeshow/iot-sensortag/bluetoothdevice.cpp | |
parent | 632e35db6d6ef6bf15891e486da983aabfb740b3 (diff) |
SensorTag changed to broadcasting mode form read-resp mode
Sensortag now sends data according to set intervals and app only
listens to signals.
Timers removed as they are no longer needed.
Both ambient and object temperature read and converted properly.
Cloud data updated with dedicated abient and object temperatures.
Version is now 1.1 (backwards compatible).
Mock data reflects to reality better.
Change-Id: I6a0325a513c1a054322f18e68d2b15c474db3ee5
Reviewed-by: Kari Hautamäki <kari.hautamaki@qt.io>
Diffstat (limited to 'tradeshow/iot-sensortag/bluetoothdevice.cpp')
-rw-r--r-- | tradeshow/iot-sensortag/bluetoothdevice.cpp | 212 |
1 files changed, 53 insertions, 159 deletions
diff --git a/tradeshow/iot-sensortag/bluetoothdevice.cpp b/tradeshow/iot-sensortag/bluetoothdevice.cpp index 66faf5a..a7b8bc4 100644 --- a/tradeshow/iot-sensortag/bluetoothdevice.cpp +++ b/tradeshow/iot-sensortag/bluetoothdevice.cpp @@ -58,18 +58,14 @@ #include <QTimer> #include <QDebug> #include <QtMath> +#include <QDateTime> Q_DECLARE_LOGGING_CATEGORY(boot2QtDemos) -// The average time from read request to read response is 150ms in optimal conditions. -// With other sensors being read we have to limit it to even longer periods. -#define RAPID_TIMER_MS 350 -#define MEDIUM_TIMER_MS (1.5*RAPID_TIMER_MS) -#define SLOW_TIMER_MS 2000 - #define START_MEASUREMENT_STR "01" /* 01 start, 00 stop */ #define DISABLE_NOTIF_STR "0000" /* 0100 enable, 0000 disable */ -#define SLOW_TIMER_TIMEOUT_STR "FA" /* 250 -> 2500ms */ +#define ENABLE_NOTIF_STR "0100" /* 0100 enable, 0000 disable */ +#define SLOW_TIMER_TIMEOUT_STR "64" /* 100 -> 1000ms */ #define MEDIUM_TIMER_TIMEOUT_STR "32" /* 50 -> 500ms */ #define RAPID_TIMER_TIMEOUT_STR "0A" /* 10 -> 100ms */ #define MOVEMENT_ENABLE_SENSORS_BITMASK_VALUE "7F02" /* see below */ @@ -85,6 +81,13 @@ Q_DECLARE_LOGGING_CATEGORY(boot2QtDemos) //MPU9250_ACCELEROMETER_RANGE_2 =0b0000_0010 = 8 G (default) //MPU9250_ACCELEROMETER_RANGE_3 =0b0000_0011 = 16 G +// These modifiers come from the Texas Intruments SensorTag Bluetooth LE API specification +#define GYROSCOPE_API_READING_MULTIPLIER (500.0 / 65536.0) +#define ACCELOMETER_API_READING_MULTIPLIER (8.0 / 32.768) +#define HUMIDITY_API_READING_MULTIPLIER (100.0 / 65536.0) +#define IR_TEMPERATURE_API_READING_DIVIDER 128.0 +#define BAROMETER_API_READING_DIVIDER 100 + typedef struct { qint16 gyrox; qint16 gyroy; @@ -107,10 +110,8 @@ BluetoothDevice::BluetoothDevice() , motionService(0) , m_deviceState(DeviceState::Disconnected) , randomAddress(false) - , slowTimer(0) - , mediumTimer(0) - , rapidTimer(0) { + lastMilliseconds = QDateTime::currentMSecsSinceEpoch(); statusUpdated("Device created"); } @@ -122,18 +123,6 @@ BluetoothDevice::BluetoothDevice(const QBluetoothDeviceInfo &d) BluetoothDevice::~BluetoothDevice() { - if (slowTimer) { - slowTimer->stop(); - delete slowTimer; - } - if (mediumTimer) { - mediumTimer->stop(); - delete mediumTimer; - } - if (rapidTimer) { - rapidTimer->stop(); - delete rapidTimer; - } delete discoveryAgent; delete controller; qDeleteAll(m_services); @@ -240,7 +229,7 @@ void BluetoothDevice::serviceScanDone() irTemperatureService = controller->createServiceObject(uuid); connect(irTemperatureService, &QLowEnergyService::stateChanged, this, &BluetoothDevice::temperatureDetailsDiscovered); - connect(irTemperatureService, &QLowEnergyService::characteristicRead, this, &BluetoothDevice::characteristicsRead); + connect(irTemperatureService, &QLowEnergyService::characteristicChanged, this, &BluetoothDevice::characteristicsRead); irTemperatureService->discoverDetails(); } if (!baroService) @@ -256,7 +245,7 @@ void BluetoothDevice::serviceScanDone() baroService = controller->createServiceObject(uuid); connect(baroService, &QLowEnergyService::stateChanged, this, &BluetoothDevice::barometerDetailsDiscovered); - connect(baroService, &QLowEnergyService::characteristicRead, this, &BluetoothDevice::characteristicsRead); + connect(baroService, &QLowEnergyService::characteristicChanged, this, &BluetoothDevice::characteristicsRead); baroService->discoverDetails(); } if (!humidityService) @@ -273,7 +262,7 @@ void BluetoothDevice::serviceScanDone() humidityService = controller->createServiceObject(uuid); connect(humidityService, &QLowEnergyService::stateChanged, this, &BluetoothDevice::humidityDetailsDiscovered); - connect(humidityService, &QLowEnergyService::characteristicRead, this, &BluetoothDevice::characteristicsRead); + connect(humidityService, &QLowEnergyService::characteristicChanged, this, &BluetoothDevice::characteristicsRead); humidityService->discoverDetails(); } @@ -291,7 +280,7 @@ void BluetoothDevice::serviceScanDone() lightService = controller->createServiceObject(uuid); connect(lightService, &QLowEnergyService::stateChanged, this, &BluetoothDevice::lightIntensityDetailsDiscovered); - connect(lightService, &QLowEnergyService::characteristicRead, this, &BluetoothDevice::characteristicsRead); + connect(lightService, &QLowEnergyService::characteristicChanged, this, &BluetoothDevice::characteristicsRead); lightService->discoverDetails(); } if (!motionService) @@ -306,7 +295,7 @@ void BluetoothDevice::serviceScanDone() } motionService = controller->createServiceObject(uuid); connect(motionService, &QLowEnergyService::stateChanged, this, &BluetoothDevice::motionDetailsDiscovered); - connect(motionService, &QLowEnergyService::characteristicRead, this, &BluetoothDevice::characteristicsRead); + connect(motionService, &QLowEnergyService::characteristicChanged, this, &BluetoothDevice::characteristicsRead); motionService->discoverDetails(); } attitudeChangeInterval.restart(); @@ -331,7 +320,7 @@ void BluetoothDevice::temperatureDetailsDiscovered(QLowEnergyService::ServiceSta if (id.toString().contains("f000aa01-0451-4000-b000-000000000000")) { //RN - irTemperatureService->writeDescriptor(characteristic.descriptors().at(0), QByteArray::fromHex(DISABLE_NOTIF_STR)); + irTemperatureService->writeDescriptor(characteristic.descriptors().at(0), QByteArray::fromHex(ENABLE_NOTIF_STR)); } if (id.toString().contains("f000aa02-0451-4000-b000-000000000000")) { //RW @@ -363,13 +352,13 @@ void BluetoothDevice::barometerDetailsDiscovered(QLowEnergyService::ServiceState qCDebug(boot2QtDemos)<<"characteristic:"<<id.toString(); if (id.toString().contains("f000aa41-0451-4000-b000-000000000000")) { - baroService->writeDescriptor(characteristic.descriptors().at(0), QByteArray::fromHex(DISABLE_NOTIF_STR)); + baroService->writeDescriptor(characteristic.descriptors().at(0), QByteArray::fromHex(ENABLE_NOTIF_STR)); } if (id.toString().contains("f000aa42-0451-4000-b000-000000000000")) { baroService->writeCharacteristic(characteristic, QByteArray::fromHex(START_MEASUREMENT_STR), QLowEnergyService::WriteWithResponse); // Start } if (id.toString().contains("f000aa44-0451-4000-b000-000000000000")) { - baroService->writeCharacteristic(characteristic, QByteArray::fromHex(SLOW_TIMER_TIMEOUT_STR), QLowEnergyService::WriteWithResponse); // Period 1 second + baroService->writeCharacteristic(characteristic, QByteArray::fromHex(MEDIUM_TIMER_TIMEOUT_STR), QLowEnergyService::WriteWithResponse); // Period 1 second } } m_barometerMeasurementStarted = true; @@ -394,7 +383,7 @@ void BluetoothDevice::humidityDetailsDiscovered(QLowEnergyService::ServiceState qCDebug(boot2QtDemos)<<"characteristic:"<<id.toString(); if (id.toString().contains("f000aa21-0451-4000-b000-000000000000")) { - humidityService->writeDescriptor(characteristic.descriptors().at(0), QByteArray::fromHex(DISABLE_NOTIF_STR)); + humidityService->writeDescriptor(characteristic.descriptors().at(0), QByteArray::fromHex(ENABLE_NOTIF_STR)); } if (id.toString().contains("f000aa22-0451-4000-b000-000000000000")) { humidityService->writeCharacteristic(characteristic, QByteArray::fromHex(START_MEASUREMENT_STR), QLowEnergyService::WriteWithResponse); // Start @@ -425,7 +414,7 @@ void BluetoothDevice::lightIntensityDetailsDiscovered(QLowEnergyService::Service qCDebug(boot2QtDemos)<<"characteristic:"<<id.toString(); if (id.toString().contains("f000aa71-0451-4000-b000-000000000000")) { - lightService->writeDescriptor(characteristic.descriptors().at(0), QByteArray::fromHex(DISABLE_NOTIF_STR)); + lightService->writeDescriptor(characteristic.descriptors().at(0), QByteArray::fromHex(ENABLE_NOTIF_STR)); } if (id.toString().contains("f000aa72-0451-4000-b000-000000000000")) { lightService->writeCharacteristic(characteristic, QByteArray::fromHex(START_MEASUREMENT_STR), QLowEnergyService::WriteWithResponse); // Start @@ -440,8 +429,13 @@ void BluetoothDevice::lightIntensityDetailsDiscovered(QLowEnergyService::Service void BluetoothDevice::motionDetailsDiscovered(QLowEnergyService::ServiceState newstate) { + // reset the time once more before we start to receive measurements. + lastMilliseconds = QDateTime::currentMSecsSinceEpoch(); + if (newstate == QLowEnergyService::ServiceDiscovered) { - connect(motionService, &QLowEnergyService::characteristicWritten, this, &BluetoothDevice::startTimers); + connect(motionService, &QLowEnergyService::characteristicWritten, [=]() { + qCDebug(boot2QtDemos) << "Wrote Characteristic - gyro"; + }); connect(motionService, static_cast<void(QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&QLowEnergyService::error), [=](QLowEnergyService::ServiceError newError) { @@ -454,65 +448,19 @@ void BluetoothDevice::motionDetailsDiscovered(QLowEnergyService::ServiceState ne qCDebug(boot2QtDemos)<<"characteristic:"<<id.toString(); if (id.toString().contains("f000aa81-0451-4000-b000-000000000000")) { - motionService->writeDescriptor(characteristic.descriptors().at(0), QByteArray::fromHex(DISABLE_NOTIF_STR)); + motionService->writeDescriptor(characteristic.descriptors().at(0), QByteArray::fromHex(ENABLE_NOTIF_STR)); } if (id.toString().contains("f000aa82-0451-4000-b000-000000000000")) { motionService->writeCharacteristic(characteristic, QByteArray::fromHex(MOVEMENT_ENABLE_SENSORS_BITMASK_VALUE), QLowEnergyService::WriteWithResponse); } if (id.toString().contains("f000aa83-0451-4000-b000-000000000000")) { - motionService->writeCharacteristic(characteristic, QByteArray::fromHex("0a"), QLowEnergyService::WriteWithResponse); + motionService->writeCharacteristic(characteristic, QByteArray::fromHex(RAPID_TIMER_TIMEOUT_STR), QLowEnergyService::WriteWithResponse); } } m_motionMeasurementStarted = true; } } -void BluetoothDevice::startTimers() { - qCDebug(boot2QtDemos) << "Wrote Characteristic - gyro, starting timers."; - if (!slowTimer) { - slowTimer = new QTimer(this); - connect(slowTimer, SIGNAL(timeout()), this, SLOT(slowTimerExpired())); - slowTimer->start(SLOW_TIMER_MS); - } - if (!mediumTimer) { - mediumTimer = new QTimer(this); - connect(mediumTimer, SIGNAL(timeout()), this, SLOT(mediumTimerExpired())); - mediumTimer->start(MEDIUM_TIMER_MS); - } - if (!rapidTimer) { - rapidTimer = new QTimer(this); - connect(rapidTimer, SIGNAL(timeout()), this, SLOT(rapidTimerExpired())); - rapidTimer->start(RAPID_TIMER_MS); - } -} - -void BluetoothDevice::slowTimerExpired() -{ - if (irTemperatureService && m_temperatureMeasurementStarted) { - queueReadRequest(temperatureCharacteristic); - } - if (baroService && m_barometerMeasurementStarted) { - queueReadRequest(barometerCharacteristic); - } - if (humidityService && m_humidityMeasurementStarted){ - queueReadRequest(humidityCharacteristic); - } -} - -void BluetoothDevice::mediumTimerExpired() -{ - if (lightService && m_lightIntensityMeasurementStarted){ - queueReadRequest(lightCharacteristic); - } -} - -void BluetoothDevice::rapidTimerExpired() -{ - if (motionService && m_motionMeasurementStarted) { - queueReadRequest(motionCharacteristic); - } -} - void BluetoothDevice::characteristicsRead(const QLowEnergyCharacteristic &info, const QByteArray &value) { switch (info.handle()) @@ -536,9 +484,6 @@ void BluetoothDevice::characteristicsRead(const QLowEnergyCharacteristic &info, qWarning() << "Invalid handle" << info.handle() << "in characteristicsRead!"; break; } - delete readRequestQueue.takeFirst(); - // Response got, now we can send new request. - sendFirstFromQueue(); } void BluetoothDevice::setState(BluetoothDevice::DeviceState state) @@ -549,76 +494,22 @@ void BluetoothDevice::setState(BluetoothDevice::DeviceState state) } } -bool BluetoothDevice::isNotInQueue(CharacteristicType characteristic) -{ - bool characteristicFound = false; - QVector<QueueData*>::const_iterator i; - for (i = readRequestQueue.constBegin(); i != readRequestQueue.constEnd(); ++i) { - if (characteristic == (*i)->typeToSend) { - characteristicFound = true; - break; - } - } - return !characteristicFound; -} - -void BluetoothDevice::queueReadRequest(CharacteristicType characteristicToRead) -{ - if (isNotInQueue(characteristicToRead)) { - readRequestQueue.append(new QueueData(characteristicToRead)); - // Try to send. If there is a request ongoing, this does nothing. - sendFirstFromQueue(); - } else { - qWarning() << "tried to add request of type " << characteristicToRead << " to queue before previous response was received!"; - } -} - -void BluetoothDevice::sendFirstFromQueue() +double BluetoothDevice::convertIrTemperatureAPIReadingToCelsius(quint16 rawReading) { - while (readRequestQueue.length() && - (false == readRequestQueue.first()->alreadySent)) { - readRequestQueue.first()->alreadySent = true; - switch (readRequestQueue.first()->typeToSend) - { - case temperatureCharacteristic: - if (irTemperatureService) - irTemperatureService->readCharacteristic(irTemperatureService->characteristic(QUuid(QString("f000aa01-0451-4000-b000-000000000000")))); - break; - case humidityCharacteristic: - if (humidityService) - humidityService->readCharacteristic(humidityService->characteristic(QUuid(QString("f000aa21-0451-4000-b000-000000000000")))); - break; - case barometerCharacteristic: - if (baroService) - baroService->readCharacteristic(baroService->characteristic(QUuid(QString("f000aa41-0451-4000-b000-000000000000")))); - break; - case motionCharacteristic: - if (motionService) - motionService->readCharacteristic(motionService->characteristic(QUuid(QString("f000aa81-0451-4000-b000-000000000000")))); - break; - case lightCharacteristic: - if (lightService) - lightService->readCharacteristic(lightService->characteristic(QUuid(QString("f000aa71-0451-4000-b000-000000000000")))); - break; - default: - delete readRequestQueue.takeFirst(); - break; - } - } + // Compute and filter final value according to TI Bluetooth LE API + const float SCALE_LSB = 0.03125; + int it = (int)((rawReading) >> 2); + float t = (float)it; + return t * SCALE_LSB; } void BluetoothDevice::irTemperatureReceived(const QByteArray &value) { - //Merge bytes - unsigned int temperature_raw = (((quint8)value.at(3)) << 8) + ((quint8)value.at(2)); - double temperature = static_cast<double>(temperature_raw); - - //Compute and filter final value - if (temperature < 32768) - temperature = temperature/128.0; //Positive temperature values - else if (temperature > 32768) - temperature = (temperature - 65536) / 128.0; //Negative temperature values - emit temperatureChanged(temperature); + const unsigned int rawObjectTemperature = (((quint8)value.at(3)) << 8) + ((quint8)value.at(2)); + const double objectTemperature = convertIrTemperatureAPIReadingToCelsius(rawObjectTemperature); + const unsigned int rawAmbientTemperature = (((quint8)value.at(1)) << 8) + ((quint8)value.at(0)); + const double ambientTemperature = convertIrTemperatureAPIReadingToCelsius(rawAmbientTemperature); + emit temperatureChanged(ambientTemperature, objectTemperature); } void BluetoothDevice::barometerReceived(const QByteArray &value) @@ -635,10 +526,10 @@ void BluetoothDevice::barometerReceived(const QByteArray &value) } double temperature = static_cast<double>(temperature_raw); - temperature /= 100; + temperature /= BAROMETER_API_READING_DIVIDER; double barometer = static_cast<double>(barometer_raw); - barometer /= 100; + barometer /= BAROMETER_API_READING_DIVIDER; emit barometerChanged(temperature, barometer); } @@ -647,7 +538,7 @@ void BluetoothDevice::humidityReceived(const QByteArray &value) //Merge bytes unsigned int humidity_raw = (((quint8)value.at(3)) << 8) + ((quint8)value.at(2)); double humidity = static_cast<double>(humidity_raw); - humidity = (humidity / 65536)*100; + humidity = humidity * HUMIDITY_API_READING_MULTIPLIER; emit humidityChanged(humidity); } @@ -660,6 +551,7 @@ void BluetoothDevice::lightIntensityReceived(const QByteArray &value) m = lightIntensity_raw & 0x0FFF; e = (lightIntensity_raw & 0xF000) >> 12; + // Compute and final value according to TI Bluetooth LE API double lightIntensity = ((double)m) * (0.01 * (double)qPow(2.0,(qreal)e)); emit lightIntensityChanged(lightIntensity); } @@ -667,7 +559,9 @@ void BluetoothDevice::lightIntensityReceived(const QByteArray &value) void BluetoothDevice::motionReceived(const QByteArray &value) { static MotionSensorData data; - data.msSincePreviousData = attitudeChangeInterval.restart(); + data.msSincePreviousData = lastMilliseconds; + lastMilliseconds = QDateTime::currentMSecsSinceEpoch(); + data.msSincePreviousData = lastMilliseconds - data.msSincePreviousData; movement_data_t values; quint8* writePtr = (quint8*)(&values); @@ -679,13 +573,13 @@ void BluetoothDevice::motionReceived(const QByteArray &value) // Data is in little endian. Fix here if needed. //Convert gyroscope and accelometer readings to proper units - data.gyroScope_x = (double(values.gyrox) * 500) / 65536; - data.gyroScope_y = (double(values.gyroy) * 500) / 65536; - data.gyroScope_z = (double(values.gyroz) * 500) / 65536; + data.gyroScope_x = double(values.gyrox) * GYROSCOPE_API_READING_MULTIPLIER; + data.gyroScope_y = double(values.gyroy) * GYROSCOPE_API_READING_MULTIPLIER; + data.gyroScope_z = double(values.gyroz) * GYROSCOPE_API_READING_MULTIPLIER; // Accelometer at 8G - data.accelometer_x = (double(values.accelx)*8) / 32.768; - data.accelometer_y = (double(values.accely)*8) / 32.768; - data.accelometer_z = (double(values.accelz)*8) / 32.768; + data.accelometer_x = double(values.accelx) * ACCELOMETER_API_READING_MULTIPLIER; + data.accelometer_y = double(values.accely) * ACCELOMETER_API_READING_MULTIPLIER; + data.accelometer_z = double(values.accelz) * ACCELOMETER_API_READING_MULTIPLIER; data.magnetometer_x = double(values.magnetomx); data.magnetometer_y = double(values.magnetomy); data.magnetometer_z = double(values.magnetomz); |