From cf2ec248f2c8d6fabc539f2acef4df5d3c0e8b6c Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 20 Sep 2017 09:35:56 +0200 Subject: iot-sensortag: Redesign of example The updated version switches the focus from having multiple sensors locally towards showing one sensor from a list. This list can display local or remote sensors and switch on runtime. Also incorporated many style fixes and cleanups. Change-Id: If7b8acbb2a784ebba95d467176e76728721c82f7 Reviewed-by: Oliver Wolff --- tradeshow/iot-sensortag/bluetoothdataprovider.cpp | 79 ++++--- tradeshow/iot-sensortag/bluetoothdataprovider.h | 9 +- tradeshow/iot-sensortag/bluetoothdevice.cpp | 64 ++--- tradeshow/iot-sensortag/bluetoothdevice.h | 54 ++--- tradeshow/iot-sensortag/clouddataprovider.cpp | 28 +-- tradeshow/iot-sensortag/clouddataproviderpool.cpp | 5 +- tradeshow/iot-sensortag/clouddataproviderpool.h | 2 +- tradeshow/iot-sensortag/cloudupdate.cpp | 14 +- tradeshow/iot-sensortag/cloudupdate.h | 2 +- tradeshow/iot-sensortag/dataproviderpool.cpp | 41 ++-- tradeshow/iot-sensortag/dataproviderpool.h | 23 +- tradeshow/iot-sensortag/demodataproviderpool.cpp | 122 +++------- tradeshow/iot-sensortag/demodataproviderpool.h | 9 +- tradeshow/iot-sensortag/main.cpp | 91 ++------ tradeshow/iot-sensortag/mockdataprovider.cpp | 39 ++-- tradeshow/iot-sensortag/mockdataprovider.h | 8 +- tradeshow/iot-sensortag/mockdataproviderpool.cpp | 5 +- tradeshow/iot-sensortag/mockdataproviderpool.h | 4 +- tradeshow/iot-sensortag/mqttdataprovider.h | 83 +++++++ tradeshow/iot-sensortag/mqttdataproviderpool.h | 72 ++++++ .../iot-sensortag/resources/base/BaseChart.qml | 2 +- .../iot-sensortag/resources/base/GyroChart.qml | 1 - .../iot-sensortag/resources/base/HumidityChart.qml | 2 - .../resources/base/MagnetometerChart.qml | 1 - .../iot-sensortag/resources/base/RotationPage.qml | 2 +- .../resources/base/SensorSettings.qml | 258 +++++++++++---------- .../iot-sensortag/resources/base/TopToolbar.qml | 55 +---- tradeshow/iot-sensortag/resources/base/main.qml | 16 +- .../iot-sensortag/resources/large/MainLarge.qml | 177 -------------- .../iot-sensortag/resources/large/StyleLarge.qml | 59 ----- .../large/images/AirPressure/AirPre_base_gauge.png | Bin 32850 -> 0 bytes .../AmbientTemperature/ambTemp_display_amb.png | Bin 7084 -> 0 bytes .../resources/large/images/General/icon_sensor.png | Bin 932 -> 0 bytes .../resources/large/images/General/separator.png | Bin 1269 -> 0 bytes .../large/images/Humidity/humidity_base_gauge.png | Bin 40846 -> 0 bytes .../large/images/Humidity/humidity_max_hum.png | Bin 1855 -> 0 bytes .../large/images/Humidity/humidity_min_hum.png | Bin 1926 -> 0 bytes .../large/images/Light/light_base_gauge.png | Bin 21149 -> 0 bytes .../large/images/Light/light_brightness.png | Bin 11928 -> 0 bytes .../ObjectTemperature/objTemp_base_circle.png | Bin 49793 -> 0 bytes .../ObjectTemperature/objTemp_display_obj.png | Bin 24610 -> 0 bytes .../iot-sensortag/resources/medium/MainMedium.qml | 177 -------------- .../iot-sensortag/resources/medium/StyleMedium.qml | 59 ----- .../images/AirPressure/AirPre_base_gauge.png | Bin 23594 -> 0 bytes .../AmbientTemperature/ambTemp_display_amb.png | Bin 4744 -> 0 bytes .../medium/images/General/icon_sensor.png | Bin 691 -> 0 bytes .../resources/medium/images/General/separator.png | Bin 966 -> 0 bytes .../medium/images/Humidity/humidity_base_gauge.png | Bin 29413 -> 0 bytes .../medium/images/Humidity/humidity_max_hum.png | Bin 1356 -> 0 bytes .../medium/images/Humidity/humidity_min_hum.png | Bin 1432 -> 0 bytes .../medium/images/Light/light_base_gauge.png | Bin 15242 -> 0 bytes .../medium/images/Light/light_brightness.png | Bin 8479 -> 0 bytes .../ObjectTemperature/objTemp_base_circle.png | Bin 35320 -> 0 bytes .../ObjectTemperature/objTemp_display_obj.png | Bin 17544 -> 0 bytes .../iot-sensortag/resources/small/MainSmall.qml | 29 +-- tradeshow/iot-sensortag/sensortagdataprovider.cpp | 54 ++--- tradeshow/iot-sensortag/sensortagdataprovider.h | 14 +- .../iot-sensortag/sensortagdataproviderpool.cpp | 77 ++---- .../iot-sensortag/sensortagdataproviderpool.h | 13 +- tradeshow/iot-sensortag/seriesstorage.cpp | 42 ++-- tradeshow/iot-sensortag/seriesstorage.h | 2 +- tradeshow/iot-sensortag/uilarge.qrc | 17 -- tradeshow/iot-sensortag/uimedium.qrc | 17 -- 63 files changed, 671 insertions(+), 1157 deletions(-) create mode 100644 tradeshow/iot-sensortag/mqttdataprovider.h create mode 100644 tradeshow/iot-sensortag/mqttdataproviderpool.h delete mode 100644 tradeshow/iot-sensortag/resources/large/MainLarge.qml delete mode 100644 tradeshow/iot-sensortag/resources/large/StyleLarge.qml delete mode 100644 tradeshow/iot-sensortag/resources/large/images/AirPressure/AirPre_base_gauge.png delete mode 100644 tradeshow/iot-sensortag/resources/large/images/AmbientTemperature/ambTemp_display_amb.png delete mode 100644 tradeshow/iot-sensortag/resources/large/images/General/icon_sensor.png delete mode 100644 tradeshow/iot-sensortag/resources/large/images/General/separator.png delete mode 100644 tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_base_gauge.png delete mode 100644 tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_max_hum.png delete mode 100644 tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_min_hum.png delete mode 100644 tradeshow/iot-sensortag/resources/large/images/Light/light_base_gauge.png delete mode 100644 tradeshow/iot-sensortag/resources/large/images/Light/light_brightness.png delete mode 100644 tradeshow/iot-sensortag/resources/large/images/ObjectTemperature/objTemp_base_circle.png delete mode 100644 tradeshow/iot-sensortag/resources/large/images/ObjectTemperature/objTemp_display_obj.png delete mode 100644 tradeshow/iot-sensortag/resources/medium/MainMedium.qml delete mode 100644 tradeshow/iot-sensortag/resources/medium/StyleMedium.qml delete mode 100644 tradeshow/iot-sensortag/resources/medium/images/AirPressure/AirPre_base_gauge.png delete mode 100644 tradeshow/iot-sensortag/resources/medium/images/AmbientTemperature/ambTemp_display_amb.png delete mode 100644 tradeshow/iot-sensortag/resources/medium/images/General/icon_sensor.png delete mode 100644 tradeshow/iot-sensortag/resources/medium/images/General/separator.png delete mode 100644 tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_base_gauge.png delete mode 100644 tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_max_hum.png delete mode 100644 tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_min_hum.png delete mode 100644 tradeshow/iot-sensortag/resources/medium/images/Light/light_base_gauge.png delete mode 100644 tradeshow/iot-sensortag/resources/medium/images/Light/light_brightness.png delete mode 100644 tradeshow/iot-sensortag/resources/medium/images/ObjectTemperature/objTemp_base_circle.png delete mode 100644 tradeshow/iot-sensortag/resources/medium/images/ObjectTemperature/objTemp_display_obj.png delete mode 100644 tradeshow/iot-sensortag/uilarge.qrc delete mode 100644 tradeshow/iot-sensortag/uimedium.qrc (limited to 'tradeshow') diff --git a/tradeshow/iot-sensortag/bluetoothdataprovider.cpp b/tradeshow/iot-sensortag/bluetoothdataprovider.cpp index 06e9fd5..3c81d92 100644 --- a/tradeshow/iot-sensortag/bluetoothdataprovider.cpp +++ b/tradeshow/iot-sensortag/bluetoothdataprovider.cpp @@ -55,9 +55,10 @@ Q_DECLARE_LOGGING_CATEGORY(boot2QtDemos) #define SAMPLE_COUNT_FOR_ZERO_ALTITUDE 10 -BluetoothDataProvider::BluetoothDataProvider(QString id, QObject *parent) - : SensorTagDataProvider(id, parent) - , m_btDevice(Q_NULLPTR) +BluetoothDataProvider::BluetoothDataProvider(const QBluetoothDeviceInfo &id, QObject *parent) + : SensorTagDataProvider(id.address().toString(), parent) + , m_info(id) + , m_btDevice(nullptr) , m_smaSamples(0) , m_zeroAltitudeSamples(0) , gyroscopeX_calibration(0) @@ -76,42 +77,52 @@ BluetoothDataProvider::~BluetoothDataProvider() bool BluetoothDataProvider::startDataFetching() { - qCDebug(boot2QtDemos) << Q_FUNC_INFO; - if (m_btDevice) { - connect(m_btDevice, &BluetoothDevice::statusUpdated, this, [=](const QString& statusMsg) { - qCDebug(boot2QtDemos) << id() << "----------" << statusMsg; - }); - connect(m_btDevice, &BluetoothDevice::stateChanged, - this, &BluetoothDataProvider::updateState); - connect(m_btDevice, &BluetoothDevice::temperatureChanged, - this, &BluetoothDataProvider::temperatureReceived); - connect(m_btDevice, &BluetoothDevice::barometerChanged, - this, &BluetoothDataProvider::barometerReceived); - connect(m_btDevice, &BluetoothDevice::humidityChanged, - this, &BluetoothDataProvider::humidityReceived); - connect(m_btDevice, &BluetoothDevice::lightIntensityChanged, - this, &BluetoothDataProvider::lightIntensityReceived); - connect(m_btDevice, &BluetoothDevice::motionChanged, - this, &BluetoothDataProvider::motionReceived); - startServiceScan(); - } + qCDebug(boot2QtDemos) << Q_FUNC_INFO << " :" << m_btDevice; + + m_btDevice = new BluetoothDevice(m_info); + + connect(m_btDevice, &BluetoothDevice::statusUpdated, this, [=](const QString& statusMsg) { + qCDebug(boot2QtDemos) << id() << "----------" << statusMsg; + }); + connect(m_btDevice, &BluetoothDevice::stateChanged, + this, &BluetoothDataProvider::updateState); + connect(m_btDevice, &BluetoothDevice::temperatureChanged, + this, &BluetoothDataProvider::temperatureReceived); + connect(m_btDevice, &BluetoothDevice::barometerChanged, + this, &BluetoothDataProvider::barometerReceived); + connect(m_btDevice, &BluetoothDevice::humidityChanged, + this, &BluetoothDataProvider::humidityReceived); + connect(m_btDevice, &BluetoothDevice::lightIntensityChanged, + this, &BluetoothDataProvider::lightIntensityReceived); + connect(m_btDevice, &BluetoothDevice::motionChanged, + this, &BluetoothDataProvider::motionReceived); + startServiceScan(); + return true; } void BluetoothDataProvider::endDataFetching() { + // BluetoothDevice is not capable of restarting + qCDebug(boot2QtDemos) << Q_FUNC_INFO << " :" << m_btDevice; + m_btDevice->disconnectFromDevice(); + setState(Scanning); + + m_btDevice->deleteLater(); + m_btDevice = nullptr; } void BluetoothDataProvider::startServiceScan() { - qCDebug(boot2QtDemos)<scanServices(); } } -void BluetoothDataProvider::temperatureReceived(double newAmbientTemperature, double newObjectTemperature) +void BluetoothDataProvider::temperatureReceived(double newAmbientTemperature, + double newObjectTemperature) { /* NOTE: We emit the signals even if value is unchanged. * Otherwise the scrolling graphs in UI will not scroll. @@ -129,17 +140,18 @@ void BluetoothDataProvider::barometerReceived(double temperature, double baromet */ barometerCelsiusTemperature = temperature; emit barometerCelsiusTemperatureChanged(); - barometerTemperatureAverage = (temperature + m_smaSamples * barometerTemperatureAverage) / (m_smaSamples + 1); + barometerTemperatureAverage = (temperature + m_smaSamples * barometerTemperatureAverage) + / (m_smaSamples + 1); m_smaSamples++; emit barometerCelsiusTemperatureAverageChanged(); - // Use a limited number of samples. It will eventually give wrong avg values, but this is just a demo... + // Use a limited number of samples. It will eventually give wrong avg values, + // but this is just a demo... if (m_smaSamples > 10000) m_smaSamples = 0; barometerHPa = barometer; emit barometer_hPaChanged(); recalibrateZeroAltitude(); - calculateZeroAltitude(); } @@ -167,7 +179,7 @@ float BluetoothDataProvider::countRotationDegrees(double degreesPerSecond, quint return ((float)degreesPerSecond) * seconds; } -void BluetoothDataProvider::motionReceived(MotionSensorData &data) +void BluetoothDataProvider::motionReceived(const MotionSensorData &data) { /* NOTE: We emit the signals even if value is unchanged. * Otherwise the scrolling graphs in UI will not scroll. @@ -222,9 +234,11 @@ QString BluetoothDataProvider::versionString() const void BluetoothDataProvider::updateState() { + if (!m_btDevice) + return; + switch (m_btDevice->state()) { case BluetoothDevice::Disconnected: - unbindDevice(); break; case BluetoothDevice::Scanning: setState(Scanning); @@ -269,13 +283,6 @@ void BluetoothDataProvider::recalibrateZeroAltitude() } } -void BluetoothDataProvider::bindToDevice(BluetoothDevice *device) -{ - if (m_btDevice) - delete m_btDevice; - m_btDevice = device; -} - void BluetoothDataProvider::unbindDevice() { if (m_btDevice) { diff --git a/tradeshow/iot-sensortag/bluetoothdataprovider.h b/tradeshow/iot-sensortag/bluetoothdataprovider.h index 5f39b4f..5c28725 100644 --- a/tradeshow/iot-sensortag/bluetoothdataprovider.h +++ b/tradeshow/iot-sensortag/bluetoothdataprovider.h @@ -55,12 +55,13 @@ #include #include #include +#include class BluetoothDataProvider : public SensorTagDataProvider { Q_OBJECT public: - BluetoothDataProvider(QString id, QObject* parent = 0); + BluetoothDataProvider(const QBluetoothDeviceInfo &id, QObject *parent = 0); virtual ~BluetoothDataProvider(); @@ -69,9 +70,8 @@ public: QString sensorType() const; QString versionString() const; - void bindToDevice(BluetoothDevice *device); void unbindDevice(); - BluetoothDevice* device(); + BluetoothDevice *device(); public slots: void startServiceScan(); @@ -80,7 +80,7 @@ public slots: void barometerReceived(double temperature, double barometer); void humidityReceived(double humidity); void lightIntensityReceived(double lightIntensity); - void motionReceived(MotionSensorData &data); + void motionReceived(const MotionSensorData &data); protected: void reset() override; @@ -89,6 +89,7 @@ protected: private: void updateState(); float countRotationDegrees(double degreesPerSecond, quint64 milliseconds); + QBluetoothDeviceInfo m_info; BluetoothDevice *m_btDevice; int m_smaSamples; int m_zeroAltitudeSamples; diff --git a/tradeshow/iot-sensortag/bluetoothdevice.cpp b/tradeshow/iot-sensortag/bluetoothdevice.cpp index 90681ed..2ede116 100644 --- a/tradeshow/iot-sensortag/bluetoothdevice.cpp +++ b/tradeshow/iot-sensortag/bluetoothdevice.cpp @@ -139,22 +139,20 @@ void BluetoothDevice::scanServices() statusUpdated("(Connecting to device...)"); // Connecting signals and slots for connecting to LE services. m_controller = new QLowEnergyController(m_deviceInfo); - connect(m_controller, SIGNAL(connected()), - this, SLOT(deviceConnected())); - connect(m_controller, SIGNAL(error(QLowEnergyController::Error)), - this, SLOT(errorReceived(QLowEnergyController::Error))); - connect(m_controller, SIGNAL(disconnected()), - this, SLOT(deviceDisconnected())); - connect(m_controller, SIGNAL(serviceDiscovered(QBluetoothUuid)), - this, SLOT(addLowEnergyService(QBluetoothUuid))); - connect(m_controller, SIGNAL(discoveryFinished()), - this, SLOT(serviceScanDone())); + connect(m_controller, &QLowEnergyController::connected, + this, &BluetoothDevice::deviceConnected); + connect(m_controller, QOverload::of(&QLowEnergyController::error), + this, &BluetoothDevice::errorReceived); + connect(m_controller, &QLowEnergyController::disconnected, + this, &BluetoothDevice::deviceDisconnected); + connect(m_controller, &QLowEnergyController::serviceDiscovered, + this, &BluetoothDevice::addLowEnergyService); + connect(m_controller, &QLowEnergyController::discoveryFinished, + this, &BluetoothDevice::serviceScanDone); m_controller->setRemoteAddressType(QLowEnergyController::PublicAddress); - m_controller->connectToDevice(); - } else { - deviceConnected(); } + m_controller->connectToDevice(); } void BluetoothDevice::addLowEnergyService(const QBluetoothUuid &serviceUuid) @@ -166,8 +164,10 @@ void BluetoothDevice::addLowEnergyService(const QBluetoothUuid &serviceUuid) qWarning() << "Could not create infrared temperature service object."; return; } - connect(m_irTemperatureService, &QLowEnergyService::stateChanged, this, &BluetoothDevice::temperatureDetailsDiscovered); - connect(m_irTemperatureService, &QLowEnergyService::characteristicChanged, this, &BluetoothDevice::updateTemperature); + connect(m_irTemperatureService, &QLowEnergyService::stateChanged, + this, &BluetoothDevice::temperatureDetailsDiscovered); + connect(m_irTemperatureService, &QLowEnergyService::characteristicChanged, + this, &BluetoothDevice::updateTemperature); m_irTemperatureService->discoverDetails(); } else if (serviceUuid == QBluetoothUuid(QLatin1String(BAROMETER_SERVICE_UUID))) { qCDebug(boot2QtDemos) << "Found barometer service."; @@ -176,8 +176,10 @@ void BluetoothDevice::addLowEnergyService(const QBluetoothUuid &serviceUuid) qWarning() << "Could not create barometer service object."; return; } - connect(m_baroService, &QLowEnergyService::stateChanged, this, &BluetoothDevice::barometerDetailsDiscovered); - connect(m_baroService, &QLowEnergyService::characteristicChanged, this, &BluetoothDevice::updatePressure); + connect(m_baroService, &QLowEnergyService::stateChanged, + this, &BluetoothDevice::barometerDetailsDiscovered); + connect(m_baroService, &QLowEnergyService::characteristicChanged, + this, &BluetoothDevice::updatePressure); m_baroService->discoverDetails(); } else if (serviceUuid == QBluetoothUuid(QLatin1String(HUMIDITYSENSOR_SERVICE_UUID))) { qCDebug(boot2QtDemos) << "Found humidity service."; @@ -186,8 +188,10 @@ void BluetoothDevice::addLowEnergyService(const QBluetoothUuid &serviceUuid) qWarning() << "Could not create humidity service object."; return; } - connect(m_humidityService, &QLowEnergyService::stateChanged, this, &BluetoothDevice::humidityDetailsDiscovered); - connect(m_humidityService, &QLowEnergyService::characteristicChanged, this, &BluetoothDevice::updateHumidity); + connect(m_humidityService, &QLowEnergyService::stateChanged, + this, &BluetoothDevice::humidityDetailsDiscovered); + connect(m_humidityService, &QLowEnergyService::characteristicChanged, + this, &BluetoothDevice::updateHumidity); m_humidityService->discoverDetails(); } else if (serviceUuid == QBluetoothUuid(QLatin1String(LIGHTSENSOR_SERVICE_UUID))) { qCDebug(boot2QtDemos) << "Found light service."; @@ -196,8 +200,10 @@ void BluetoothDevice::addLowEnergyService(const QBluetoothUuid &serviceUuid) qWarning() << "Could not create light service object."; return; } - connect(m_lightService, &QLowEnergyService::stateChanged, this, &BluetoothDevice::lightIntensityDetailsDiscovered); - connect(m_lightService, &QLowEnergyService::characteristicChanged, this, &BluetoothDevice::updateLight); + connect(m_lightService, &QLowEnergyService::stateChanged, + this, &BluetoothDevice::lightIntensityDetailsDiscovered); + connect(m_lightService, &QLowEnergyService::characteristicChanged, + this, &BluetoothDevice::updateLight); m_lightService->discoverDetails(); } else if (serviceUuid == QBluetoothUuid(QLatin1String(MOTIONSENSOR_SERVICE_UUID))) { qCDebug(boot2QtDemos) << "Found motion service."; @@ -206,8 +212,10 @@ void BluetoothDevice::addLowEnergyService(const QBluetoothUuid &serviceUuid) qWarning() << "Could not create motion service object."; return; } - connect(m_motionService, &QLowEnergyService::stateChanged, this, &BluetoothDevice::motionDetailsDiscovered); - connect(m_motionService, &QLowEnergyService::characteristicChanged, this, &BluetoothDevice::updateMotionValue); + connect(m_motionService, &QLowEnergyService::stateChanged, + this, &BluetoothDevice::motionDetailsDiscovered); + connect(m_motionService, &QLowEnergyService::characteristicChanged, + this, &BluetoothDevice::updateMotionValue); m_motionService->discoverDetails(); } else { qCDebug(boot2QtDemos) << "Found unhandled service with id" << serviceUuid << "."; @@ -243,7 +251,7 @@ void BluetoothDevice::temperatureDetailsDiscovered(QLowEnergyService::ServiceSta qCDebug(boot2QtDemos) << "Wrote Characteristic - temperature"; }); - connect(m_irTemperatureService, static_cast(&QLowEnergyService::error), + connect(m_irTemperatureService, QOverload::of(&QLowEnergyService::error), [=](QLowEnergyService::ServiceError newError) { qCDebug(boot2QtDemos) << "error while writing - temperature:" << newError; }); @@ -282,7 +290,7 @@ void BluetoothDevice::barometerDetailsDiscovered(QLowEnergyService::ServiceState qCDebug(boot2QtDemos) << "Wrote Characteristic - barometer"; }); - connect(m_baroService, static_cast(&QLowEnergyService::error), + connect(m_baroService, QOverload::of(&QLowEnergyService::error), [=](QLowEnergyService::ServiceError newError) { qCDebug(boot2QtDemos) << "error while writing - barometer:" << newError; }); @@ -322,7 +330,7 @@ void BluetoothDevice::humidityDetailsDiscovered(QLowEnergyService::ServiceState qCDebug(boot2QtDemos) << "Wrote Characteristic - humidity"; }); - connect(m_humidityService, static_cast(&QLowEnergyService::error), + connect(m_humidityService, QOverload::of(&QLowEnergyService::error), [=](QLowEnergyService::ServiceError newError) { qCDebug(boot2QtDemos) << "error while writing - humidity:" << newError; }); @@ -362,7 +370,7 @@ void BluetoothDevice::lightIntensityDetailsDiscovered(QLowEnergyService::Service qCDebug(boot2QtDemos) << "Wrote Characteristic - light intensity"; }); - connect(m_lightService, static_cast(&QLowEnergyService::error), + connect(m_lightService, QOverload::of(&QLowEnergyService::error), [=](QLowEnergyService::ServiceError newError) { qCDebug(boot2QtDemos) << "error while writing - light intensity:" << newError; }); @@ -405,7 +413,7 @@ void BluetoothDevice::motionDetailsDiscovered(QLowEnergyService::ServiceState ne qCDebug(boot2QtDemos) << "Wrote Characteristic - gyro"; }); - connect(m_motionService, static_cast(&QLowEnergyService::error), + connect(m_motionService, QOverload::of(&QLowEnergyService::error), [=](QLowEnergyService::ServiceError newError) { qCDebug(boot2QtDemos) << "error while writing - gyro:" << newError; }); diff --git a/tradeshow/iot-sensortag/bluetoothdevice.h b/tradeshow/iot-sensortag/bluetoothdevice.h index ed74866..5f114ea 100644 --- a/tradeshow/iot-sensortag/bluetoothdevice.h +++ b/tradeshow/iot-sensortag/bluetoothdevice.h @@ -63,28 +63,16 @@ class MotionSensorData { public: - double gyroScope_x; - double gyroScope_y; - double gyroScope_z; - double accelometer_x; - double accelometer_y; - double accelometer_z; - double magnetometer_x; - double magnetometer_y; - double magnetometer_z; - quint64 msSincePreviousData; - MotionSensorData() { - gyroScope_x = 0; - gyroScope_y = 0; - gyroScope_z = 0; - accelometer_x = 0; - accelometer_y = 0; - accelometer_z = 0; - magnetometer_x = 0; - magnetometer_y = 0; - magnetometer_z = 0; - msSincePreviousData = 0; - } + double gyroScope_x{}; + double gyroScope_y{}; + double gyroScope_z{}; + double accelometer_x{}; + double accelometer_y{}; + double accelometer_z{}; + double magnetometer_x{}; + double magnetometer_y{}; + double magnetometer_z{}; + quint64 msSincePreviousData{}; }; typedef enum CharacteristicType { @@ -105,7 +93,12 @@ class BluetoothDevice: public QObject Q_PROPERTY(DeviceState state READ state NOTIFY stateChanged) public: - enum DeviceState {Disconnected = 0, Scanning, Connected, Error}; + enum DeviceState { + Disconnected = 0, + Scanning, + Connected, + Error + }; Q_ENUM(DeviceState) BluetoothDevice(); @@ -124,7 +117,7 @@ signals: void barometerChanged(double temperature, double barometer); void humidityChanged(double humidity); void lightIntensityChanged(double intensity); - void motionChanged(MotionSensorData& data); + void motionChanged(MotionSensorData data); void statusUpdated(QString statusMsg); public slots: @@ -170,11 +163,11 @@ private: void updateServiceDetails(); QLowEnergyController *m_controller; - QLowEnergyService* m_irTemperatureService; - QLowEnergyService* m_baroService; - QLowEnergyService* m_humidityService; - QLowEnergyService* m_lightService; - QLowEnergyService* m_motionService; + QLowEnergyService *m_irTemperatureService; + QLowEnergyService *m_baroService; + QLowEnergyService *m_humidityService; + QLowEnergyService *m_lightService; + QLowEnergyService *m_motionService; DeviceState m_deviceState; bool m_temperatureMeasurementStarted; bool m_barometerMeasurementStarted; @@ -182,11 +175,8 @@ private: bool m_lightIntensityMeasurementStarted; bool m_motionMeasurementStarted; quint64 m_lastMilliseconds; - QBluetoothDeviceInfo m_deviceInfo; - SensorTagDataProvider *m_dataProvider; - QTimer *m_serviceDetailsTimer; }; diff --git a/tradeshow/iot-sensortag/clouddataprovider.cpp b/tradeshow/iot-sensortag/clouddataprovider.cpp index 0c2bd0f..aa5a26c 100644 --- a/tradeshow/iot-sensortag/clouddataprovider.cpp +++ b/tradeshow/iot-sensortag/clouddataprovider.cpp @@ -55,7 +55,7 @@ #define MAJOR_VERSION_NUMBER 1 #define MINOR_VERSION_NUMBER 1 -#define CLOUD_DATA_POLL_INTERVAL_MS 1000 /* 1 second update interval */ +#define CLOUD_DATA_POLL_INTERVAL_MS 1000 /* 1 second update interval */ #ifndef QT_NO_SSL static QString dataFetchUrl = "https://ottoryynanenqt.blob.core.windows.net/btsensortagreadings/sensorTagReadings.txt"; #else @@ -64,9 +64,9 @@ static QString dataFetchUrl = "http://ottoryynanenqt.blob.core.windows.net/btsen Q_DECLARE_LOGGING_CATEGORY(boot2QtDemos) -CloudDataProvider::CloudDataProvider(QString id, QObject* parent) +CloudDataProvider::CloudDataProvider(QString id, QObject *parent) : SensorTagDataProvider(id, parent) - , reply(Q_NULLPTR) + , reply(nullptr) { intervalRotation = CLOUD_DATA_POLL_INTERVAL_MS; connect(&qnam, &QNetworkAccessManager::authenticationRequired, @@ -79,8 +79,9 @@ CloudDataProvider::CloudDataProvider(QString id, QObject* parent) bool CloudDataProvider::startDataFetching() { + setState(Connected); pollTimer = new QTimer(this); - connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollTimerExpired())); + connect(pollTimer, &QTimer::timeout, this, &CloudDataProvider::pollTimerExpired); pollTimer->start(CLOUD_DATA_POLL_INTERVAL_MS); return true; } @@ -105,7 +106,8 @@ void CloudDataProvider::parseReceivedText() if ((MAJOR_VERSION_NUMBER < dataMajorVersion) || // Major version not supported OR ((MAJOR_VERSION_NUMBER == dataMajorVersion) && // Major version OK but (MINOR_VERSION_NUMBER < dataMinorVersion))) { // Minor version not supported - qWarning() << Q_FUNC_INFO << "Version" << dataList[3] << "not supported by version" << QString::number(MAJOR_VERSION_NUMBER)+"."+QString::number(MINOR_VERSION_NUMBER); + qWarning() << Q_FUNC_INFO << "Version" << dataList[3] << "not supported by version" + << QString::number(MAJOR_VERSION_NUMBER)+"."+QString::number(MINOR_VERSION_NUMBER); return; } // Header OK, parse data. @@ -113,10 +115,10 @@ void CloudDataProvider::parseReceivedText() bool accelometerReadingGot = false; bool magnetometerReadingGot = false; bool rotationReadingsGot = false; - for (int stringIndex = 4 ; stringIndex < (dataList.length()-1) ; stringIndex+=2) { + for (int stringIndex = 4; stringIndex < (dataList.length() - 1); stringIndex += 2) { const QString headerText(dataList[stringIndex]); - const double doubleValue = QString(dataList[stringIndex+1]).toDouble(); - const float floatValue = QString(dataList[stringIndex+1]).toFloat(); + const double doubleValue = QString(dataList[stringIndex + 1]).toDouble(); + const float floatValue = QString(dataList[stringIndex + 1]).toFloat(); /* NOTE: We emit the signals even if value is unchanged. * Otherwise the scrolling graphs in UI will not scroll. */ @@ -216,10 +218,8 @@ void CloudDataProvider::httpFinished() } parseReceivedText(); - const QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - reply->deleteLater(); - reply = Q_NULLPTR; + reply = nullptr; } void CloudDataProvider::httpReadyRead() @@ -232,7 +232,7 @@ void CloudDataProvider::httpReadyRead() } #ifndef QT_NO_SSL -void CloudDataProvider::sslErrors(QNetworkReply*, const QList &errors) +void CloudDataProvider::sslErrors(QNetworkReply *, const QList &errors) { QString errorString; for (const QSslError &error : errors) { @@ -246,7 +246,7 @@ void CloudDataProvider::sslErrors(QNetworkReply*, const QList &errors } #endif -void CloudDataProvider::slotAuthenticationRequired(QNetworkReply*, QAuthenticator *authenticator) +void CloudDataProvider::slotAuthenticationRequired(QNetworkReply *, QAuthenticator *authenticator) { Q_UNUSED(authenticator); } @@ -258,5 +258,5 @@ QString CloudDataProvider::sensorType() const QString CloudDataProvider::versionString() const { - return QString::number(MAJOR_VERSION_NUMBER)+"."+QString::number(MINOR_VERSION_NUMBER); + return QString::number(MAJOR_VERSION_NUMBER) + "." + QString::number(MINOR_VERSION_NUMBER); } diff --git a/tradeshow/iot-sensortag/clouddataproviderpool.cpp b/tradeshow/iot-sensortag/clouddataproviderpool.cpp index 7265059..5b69803 100644 --- a/tradeshow/iot-sensortag/clouddataproviderpool.cpp +++ b/tradeshow/iot-sensortag/clouddataproviderpool.cpp @@ -50,7 +50,7 @@ #include "clouddataproviderpool.h" #include "clouddataprovider.h" -CloudDataProviderPool::CloudDataProviderPool(QObject* parent) +CloudDataProviderPool::CloudDataProviderPool(QObject *parent) : DataProviderPool(parent) { m_poolName = "Cloud"; @@ -60,9 +60,8 @@ void CloudDataProviderPool::startScanning() { qDeleteAll(m_dataProviders); m_dataProviders.clear(); - m_dataProviders.push_back(new CloudDataProvider("CLOUD_PROVIDER", this)); - m_dataProviders.at(0)->startDataFetching(); + emit providerConnected("MS_AZURE_CLOUD"); emit providersUpdated(); emit dataProvidersChanged(); diff --git a/tradeshow/iot-sensortag/clouddataproviderpool.h b/tradeshow/iot-sensortag/clouddataproviderpool.h index 5a357c0..3a13a19 100644 --- a/tradeshow/iot-sensortag/clouddataproviderpool.h +++ b/tradeshow/iot-sensortag/clouddataproviderpool.h @@ -57,7 +57,7 @@ class CloudDataProvider; class CloudDataProviderPool : public DataProviderPool { public: - explicit CloudDataProviderPool(QObject* parent = 0); + explicit CloudDataProviderPool(QObject *parent = 0); void startScanning() override; }; diff --git a/tradeshow/iot-sensortag/cloudupdate.cpp b/tradeshow/iot-sensortag/cloudupdate.cpp index 122fd9e..b43c097 100644 --- a/tradeshow/iot-sensortag/cloudupdate.cpp +++ b/tradeshow/iot-sensortag/cloudupdate.cpp @@ -47,11 +47,11 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include "cloudupdate.h" #include "cloudservice.h" #include "dataproviderpool.h" #include "sensortagdataprovider.h" - #include "demodataproviderpool.h" #include "was/storage_account.h" @@ -72,11 +72,10 @@ CloudUpdate::CloudUpdate(QObject *parent) void CloudUpdate::setDataProviderPool(DataProviderPool *provider) { m_providerPool = provider; - connect(m_providerPool, &DataProviderPool::providerForCloudChanged, this, [=]() { - m_provider = m_providerPool->providerForCloud(); - if (!m_provider) { + connect(m_providerPool, &DataProviderPool::currentProviderChanged, this, [=]() { + m_provider = m_providerPool->currentProvider(); + if (!m_provider) stop(); - } }); } @@ -126,7 +125,7 @@ void CloudUpdate::writeToCloud() #ifndef Q_OS_WIN const utility::string_t storage_connection_string(U(accStr.data())); #else - const utility::string_t storage_connection_string(reinterpret_cast(QString(accStr).utf16())); + const utility::string_t storage_connection_string(reinterpret_cast(QString(accStr).utf16())); #endif azure::storage::cloud_blob_container container; @@ -154,7 +153,7 @@ void CloudUpdate::writeToCloud() #ifndef Q_OS_WIN blob.upload_text(U(sensorData.toLocal8Bit().data())); #else - blob.upload_text(reinterpret_cast(sensorData.utf16())); + blob.upload_text(reinterpret_cast(sensorData.utf16())); #endif } @@ -181,5 +180,6 @@ QString CloudUpdate::buildString() const exportString += QString("RotX:\n%1\n").arg(m_provider->getRotationX(), 0, 'f', ROUNDING_DECIMALS); exportString += QString("RotY:\n%1\n").arg(m_provider->getRotationY(), 0, 'f', ROUNDING_DECIMALS); exportString += QString("RotZ:\n%1").arg(m_provider->getRotationZ(), 0, 'f', ROUNDING_DECIMALS); + return exportString; } diff --git a/tradeshow/iot-sensortag/cloudupdate.h b/tradeshow/iot-sensortag/cloudupdate.h index 9fa81cf..f6026ce 100644 --- a/tradeshow/iot-sensortag/cloudupdate.h +++ b/tradeshow/iot-sensortag/cloudupdate.h @@ -68,7 +68,7 @@ public: void stop(); protected: - void timerEvent(QTimerEvent* event); + void timerEvent(QTimerEvent *event); virtual void writeToCloud(); diff --git a/tradeshow/iot-sensortag/dataproviderpool.cpp b/tradeshow/iot-sensortag/dataproviderpool.cpp index 77c4514..66d9480 100644 --- a/tradeshow/iot-sensortag/dataproviderpool.cpp +++ b/tradeshow/iot-sensortag/dataproviderpool.cpp @@ -51,12 +51,16 @@ DataProviderPool::DataProviderPool(QObject *parent) : QObject(parent) + , m_currentProvider(nullptr) + , m_currentProviderIndex(-1) { } DataProviderPool::DataProviderPool(QString poolName, QObject *parent) : QObject(parent) , m_poolName(poolName) + , m_currentProvider(nullptr) + , m_currentProviderIndex(-1) { } @@ -70,21 +74,7 @@ void DataProviderPool::stopScanning() emit scanFinished(); } -SensorTagDataProvider *DataProviderPool::getProvider(SensorTagDataProvider::TagType type) const -{ - auto it = m_dataProviders.constBegin(); - SensorTagDataProvider* p = 0; - while (it != m_dataProviders.end()) { - if ((*it)->tagType() & type) { - p = *it; - break; - } - it++; - } - return p; -} - -void DataProviderPool::disconnectProvider(QString id) +void DataProviderPool::disconnectProvider(const QString &id) { Q_UNUSED(id) } @@ -98,3 +88,24 @@ SensorTagDataProvider *DataProviderPool::providerForCloud() const { return 0; } + +SensorTagDataProvider *DataProviderPool::currentProvider() const +{ + return m_currentProvider; +} + +int DataProviderPool::currentProviderIndex() const +{ + return m_currentProviderIndex; +} + +void DataProviderPool::setCurrentProviderIndex(int currentProviderIndex) +{ + if (m_currentProviderIndex == currentProviderIndex) + return; + + m_currentProviderIndex = currentProviderIndex; + m_currentProvider = m_dataProviders.at(m_currentProviderIndex); + emit currentProviderIndexChanged(m_currentProviderIndex); + emit currentProviderChanged(m_currentProvider); +} diff --git a/tradeshow/iot-sensortag/dataproviderpool.h b/tradeshow/iot-sensortag/dataproviderpool.h index 9c14504..e060758 100644 --- a/tradeshow/iot-sensortag/dataproviderpool.h +++ b/tradeshow/iot-sensortag/dataproviderpool.h @@ -58,18 +58,25 @@ class DataProviderPool : public QObject { Q_OBJECT - Q_PROPERTY (QQmlListProperty dataProviders READ dataProviders NOTIFY dataProvidersChanged) + Q_PROPERTY(QQmlListProperty dataProviders READ dataProviders NOTIFY dataProvidersChanged) + Q_PROPERTY(SensorTagDataProvider* currentProvider READ currentProvider NOTIFY currentProviderChanged) + Q_PROPERTY(int currentProviderIndex READ currentProviderIndex WRITE setCurrentProviderIndex NOTIFY currentProviderIndexChanged) Q_PROPERTY(QString name MEMBER m_poolName CONSTANT) public: Q_INVOKABLE virtual void startScanning(); Q_INVOKABLE virtual void stopScanning(); - Q_INVOKABLE virtual SensorTagDataProvider* getProvider(SensorTagDataProvider::TagType type) const; - Q_INVOKABLE virtual void disconnectProvider(QString id); + Q_INVOKABLE virtual void disconnectProvider(const QString &id); + Q_INVOKABLE virtual SensorTagDataProvider *currentProvider() const; + Q_INVOKABLE virtual int currentProviderIndex() const; QQmlListProperty dataProviders(); - virtual SensorTagDataProvider* providerForCloud() const; + virtual SensorTagDataProvider *providerForCloud() const; + + +public slots: + void setCurrentProviderIndex(int currentProviderIndex); signals: void providerConnected(QString id); @@ -80,14 +87,18 @@ signals: void scanFinished(); void providerForCloudChanged(); void dataProvidersChanged(); + void currentProviderChanged(SensorTagDataProvider* currentProvider); + void currentProviderIndexChanged(int currentProviderIndex); protected: explicit DataProviderPool(QObject *parent = 0); - DataProviderPool(QString poolName, QObject* parent = 0); + DataProviderPool(QString poolName, QObject *parent = 0); protected: - QList m_dataProviders; + QList m_dataProviders; QString m_poolName; + SensorTagDataProvider *m_currentProvider; + int m_currentProviderIndex; }; #endif // DATAPROVIDERPOOL_H diff --git a/tradeshow/iot-sensortag/demodataproviderpool.cpp b/tradeshow/iot-sensortag/demodataproviderpool.cpp index f9a219d..4689a1c 100644 --- a/tradeshow/iot-sensortag/demodataproviderpool.cpp +++ b/tradeshow/iot-sensortag/demodataproviderpool.cpp @@ -83,7 +83,7 @@ QString DemoCloudProvider::versionString() const double DemoCloudProvider::getRelativeHumidity() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Humidity) return p->getRelativeHumidity(); } @@ -92,7 +92,7 @@ double DemoCloudProvider::getRelativeHumidity() const double DemoCloudProvider::getInfraredAmbientTemperature() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::AmbientTemperature) return p->getInfraredAmbientTemperature(); } @@ -101,7 +101,7 @@ double DemoCloudProvider::getInfraredAmbientTemperature() const double DemoCloudProvider::getInfraredObjectTemperature() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::ObjectTemperature) return p->getInfraredObjectTemperature(); } @@ -110,7 +110,7 @@ double DemoCloudProvider::getInfraredObjectTemperature() const double DemoCloudProvider::getLightIntensityLux() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Light) return p->getLightIntensityLux(); } @@ -119,7 +119,7 @@ double DemoCloudProvider::getLightIntensityLux() const double DemoCloudProvider::getBarometerCelsiusTemperature() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::AirPressure) return p->getBarometerCelsiusTemperature(); } @@ -128,7 +128,7 @@ double DemoCloudProvider::getBarometerCelsiusTemperature() const double DemoCloudProvider::getBarometerTemperatureAverage() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::AirPressure) return p->getBarometerTemperatureAverage(); } @@ -137,7 +137,7 @@ double DemoCloudProvider::getBarometerTemperatureAverage() const double DemoCloudProvider::getBarometer_hPa() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::AirPressure) return p->getBarometer_hPa(); } @@ -146,7 +146,7 @@ double DemoCloudProvider::getBarometer_hPa() const float DemoCloudProvider::getGyroscopeX_degPerSec() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Magnetometer) return p->getGyroscopeX_degPerSec(); } @@ -155,7 +155,7 @@ float DemoCloudProvider::getGyroscopeX_degPerSec() const float DemoCloudProvider::getGyroscopeY_degPerSec() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Magnetometer) return p->getGyroscopeY_degPerSec(); } @@ -164,7 +164,7 @@ float DemoCloudProvider::getGyroscopeY_degPerSec() const float DemoCloudProvider::getGyroscopeZ_degPerSec() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Magnetometer) return p->getGyroscopeZ_degPerSec(); } @@ -173,7 +173,7 @@ float DemoCloudProvider::getGyroscopeZ_degPerSec() const float DemoCloudProvider::getAccelometer_xAxis() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Accelometer) return p->getAccelometer_xAxis(); } @@ -182,7 +182,7 @@ float DemoCloudProvider::getAccelometer_xAxis() const float DemoCloudProvider::getAccelometer_yAxis() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Accelometer) return p->getAccelometer_yAxis(); } @@ -191,7 +191,7 @@ float DemoCloudProvider::getAccelometer_yAxis() const float DemoCloudProvider::getAccelometer_zAxis() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Accelometer) return p->getAccelometer_zAxis(); } @@ -200,7 +200,7 @@ float DemoCloudProvider::getAccelometer_zAxis() const float DemoCloudProvider::getMagnetometerMicroT_xAxis() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Magnetometer) return p->getMagnetometerMicroT_xAxis(); } @@ -209,7 +209,7 @@ float DemoCloudProvider::getMagnetometerMicroT_xAxis() const float DemoCloudProvider::getMagnetometerMicroT_yAxis() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Magnetometer) return p->getMagnetometerMicroT_yAxis(); } @@ -218,7 +218,7 @@ float DemoCloudProvider::getMagnetometerMicroT_yAxis() const float DemoCloudProvider::getMagnetometerMicroT_zAxis() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Magnetometer) return p->getMagnetometerMicroT_zAxis(); } @@ -227,7 +227,7 @@ float DemoCloudProvider::getMagnetometerMicroT_zAxis() const float DemoCloudProvider::getRotationX() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Rotation) return p->getRotationX(); } @@ -236,7 +236,7 @@ float DemoCloudProvider::getRotationX() const float DemoCloudProvider::getRotationY() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Rotation) return p->getRotationY(); } @@ -245,7 +245,7 @@ float DemoCloudProvider::getRotationY() const float DemoCloudProvider::getRotationZ() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Rotation) return p->getRotationZ(); } @@ -254,7 +254,7 @@ float DemoCloudProvider::getRotationZ() const float DemoCloudProvider::getAltitude() const { - for (SensorTagDataProvider *p : qAsConst(m_dataProviders)) { + for (SensorTagDataProvider *p: qAsConst(m_dataProviders)) { if (p->tagType() & SensorTagDataProvider::Altitude) return p->getAltitude(); } @@ -272,74 +272,28 @@ DemoDataProviderPool::DemoDataProviderPool(QObject *parent) void DemoDataProviderPool::startScanning() { - if (m_mockData) { - qDeleteAll(m_dataProviders); - m_dataProviders.clear(); - - MockDataProvider* p = new MockDataProvider("MOCK_PROVIDER_1", this); - p->setTagType(SensorTagDataProvider::ObjectTemperature | SensorTagDataProvider::AmbientTemperature | SensorTagDataProvider::Rotation); - m_dataProviders.push_back(p); - p = new MockDataProvider("MOCK_PROVIDER_2", this); - p->setTagType(SensorTagDataProvider::Humidity | SensorTagDataProvider::Light | SensorTagDataProvider::Accelometer); - m_dataProviders.push_back(p); - p = new MockDataProvider("MOCK_PROVIDER_3", this); - p->setTagType(SensorTagDataProvider::Magnetometer | SensorTagDataProvider::AirPressure); - m_dataProviders.push_back(p); - for (int i=0; i < m_dataProviders.length(); i++) { - m_dataProviders.at(i)->startDataFetching(); - emit providerConnected(p->id()); - } - // Stop scanning as we already have a provider - finishScanning(); - } - else { - if (!m_initialized) { - // Create a DataProvider objects early on for UI to be able to - // show all data providers as available. The BT device information - // will be added later on when the Bluetooth device has been found - for (const QString& id : m_macFilters) { - BluetoothDataProvider *p = new BluetoothDataProvider(id, this); - m_dataProviders.push_back(p); - // Set initial state to Scanning for UI to be - // able to show "Connecting.." information - p->setState(SensorTagDataProvider::Scanning); - // Empty tag type, it will be set next - p->setTagType(0); - } - // Fake that we have set of sensors with different capabilities - // by assigning only some of the sensor data types to each sensor tag - int i = 0; - while (i < SensorTagDataProvider::tagTypeCount) { - for (int p = 0; p < m_dataProviders.count() && i < SensorTagDataProvider::tagTypeCount; p++) { - SensorTagDataProvider *provider = m_dataProviders.at(p); - int tagType = provider->tagType() | (1 << i++); - provider->setTagType(tagType); - qCDebug(boot2QtDemos) << "Set tag type for provider" << provider->id() << "to" << QString::number(tagType, 2); - } - } - emit dataProvidersChanged(); - m_initialized = true; - } - SensorTagDataProviderPool::startScanning(); - } + qDeleteAll(m_dataProviders); + m_dataProviders.clear(); + + MockDataProvider* p = new MockDataProvider("MOCK_PROVIDER_1", this); + p->setTagType(SensorTagDataProvider::ObjectTemperature | SensorTagDataProvider::AmbientTemperature | SensorTagDataProvider::Rotation); + m_dataProviders.push_back(p); + p = new MockDataProvider("MOCK_PROVIDER_2", this); + p->setTagType(SensorTagDataProvider::Humidity | SensorTagDataProvider::Light | SensorTagDataProvider::Accelometer); + m_dataProviders.push_back(p); + p = new MockDataProvider("MOCK_PROVIDER_3", this); + p->setTagType(SensorTagDataProvider::Magnetometer | SensorTagDataProvider::AirPressure); + m_dataProviders.push_back(p); + for (int i=0; i < m_dataProviders.length(); i++) + emit providerConnected(p->id()); + // Stop scanning as we already have a provider + finishScanning(); + + SensorTagDataProviderPool::startScanning(); } void DemoDataProviderPool::finishScanning() { - if (m_dataProviders.length() && m_mockData) { - // For mock data we have only one provider and - // it servers as the provider to the cloud, too - m_cloudProvider = m_dataProviders.at(0); - emit providerForCloudChanged(); - } else { - m_cloudProvider = new DemoCloudProvider(this); - static_cast(m_cloudProvider)->setDataProviders(m_dataProviders); - for (SensorTagDataProvider *p : m_dataProviders) { - // If BluetoothDevice object is not attached, the device has not been found - if (!static_cast(p)->device()) - p->setState(SensorTagDataProvider::NotFound); - } - } emit dataProvidersChanged(); emit scanFinished(); } diff --git a/tradeshow/iot-sensortag/demodataproviderpool.h b/tradeshow/iot-sensortag/demodataproviderpool.h index 7d2e939..b6b6b53 100644 --- a/tradeshow/iot-sensortag/demodataproviderpool.h +++ b/tradeshow/iot-sensortag/demodataproviderpool.h @@ -62,8 +62,7 @@ public: void startScanning() override; - SensorTagDataProvider* providerForCloud() const override; - + SensorTagDataProvider *providerForCloud() const override; void setMockDataMode(bool mode); protected: @@ -71,7 +70,7 @@ protected: private: bool m_mockData; - SensorTagDataProvider* m_cloudProvider; + SensorTagDataProvider *m_cloudProvider; bool m_initialized; }; @@ -82,7 +81,7 @@ class DemoCloudProvider : public SensorTagDataProvider public: explicit DemoCloudProvider(QObject *parent); - void setDataProviders(const QList& dataProviders); + void setDataProviders(const QList &dataProviders); QString sensorType() const override; QString versionString() const override; @@ -108,7 +107,7 @@ public: float getRotationZ() const override; float getAltitude() const override; - QList m_dataProviders; + QList m_dataProviders; }; #endif // DEMODATAPROVIDERPOOL_H diff --git a/tradeshow/iot-sensortag/main.cpp b/tradeshow/iot-sensortag/main.cpp index 5164919..30c8813 100644 --- a/tradeshow/iot-sensortag/main.cpp +++ b/tradeshow/iot-sensortag/main.cpp @@ -81,63 +81,29 @@ int main(int argc, char *argv[]) QFontDatabase::addApplicationFont(QString::fromLatin1(":/resources/base/fonts/titilliumweb/TitilliumWeb-Regular.ttf")); app.setFont(QFont("Titillium Web", 13)); - DataProviderPool *dataProviderPool = 0; + DataProviderPool *remoteProviderPool = nullptr; + DataProviderPool *localProviderPool = nullptr; SeriesStorage seriesStorage; QCommandLineParser parser; - parser.addOptions({{"source", "Sensor data source", "cloud | sensor | mock"}, {"fullscreen", "Fullscreen mode", "true | false"}}); + parser.addOptions({{"fullscreen", "Fullscreen mode", "true | false"}}); parser.addHelpOption(); parser.process(app); - QString sensorSource = parser.value("source"); - - if (sensorSource.isEmpty()) - sensorSource = qgetenv("QT_IOT_DEMO_DATA_SOURCE"); - - if (sensorSource.isEmpty()) - // There is no wastorage package available for WinRT -#ifdef Q_OS_WINRT - sensorSource = "mock"; -#else - sensorSource = "cloud"; -#endif - - if (sensorSource == QString("cloud").toLower()) { - qCDebug(boot2QtDemos) << "Running in cloud mode"; - dataProviderPool = new CloudDataProviderPool; - } #if defined(RUNS_AS_HOST) - else if (sensorSource == QString("sensor").toLower()) { - qCDebug(boot2QtDemos) << "Running in sensor mode"; - dataProviderPool = new DemoDataProviderPool; - // List of devices used in Embedded World - static_cast(dataProviderPool)->setMacFilterList(QStringList() << - "24:71:89:BF:3B:82" << - "24:71:89:BC:44:82"); - } +// localProviderPool = new MockDataProviderPool; + localProviderPool = new DemoDataProviderPool; #endif - else if (sensorSource == QString("mock").toLower()){ - qCDebug(boot2QtDemos) << "Running in mock data mode"; - dataProviderPool = new MockDataProviderPool; - } - else { - qCDebug(boot2QtDemos) << "Unknown mode: " << sensorSource; - return 1; - } - - seriesStorage.setDataProviderPool(dataProviderPool); + seriesStorage.setDataProviderPool(remoteProviderPool); qmlRegisterType("SensorTag.DataProvider", 1, 0, "SensorTagData"); - qmlRegisterType("SensorTag.DataProvider", 1, 0, "ProviderState"); qmlRegisterType("SensorTag.DataProvider", 1, 0, "DataProviderPool"); qmlRegisterType("SensorTag.SeriesStorage", 1, 0, "SeriesStorage"); #if defined(RUNS_AS_HOST) && defined(AZURE_UPLOAD) CloudUpdate update; - if (sensorSource == "sensor" || sensorSource == "mock") { - update.setDataProviderPool(dataProviderPool); - update.restart(); - } + update.setDataProviderPool(localProviderPool); + update.restart(); #endif #ifdef DEPLOY_TO_FS @@ -169,34 +135,13 @@ int main(int argc, char *argv[]) addressString.append(QLatin1Char('/')); } } -#if defined(UI_SMALL) - mainFile = namingScheme + QStringLiteral("/resources/small/MainSmall.qml"); - styleFile = namingScheme + QStringLiteral("/resources/small/StyleSmall.qml"); - - uiVariant = "small"; - fullScreen = true; - appWidth = 1920; - appHeight = 1080; - qCDebug(boot2QtDemos) << "Using SMALL UI variant"; -#elif defined(UI_MEDIUM) - mainFile =QStringLiteral("qrc:/resources/medium/MainMedium.qml"); - styleFile = QUrl("qrc:/resources/medium/StyleMedium.qml"); - uiVariant = "medium"; - fullScreen = true; - appWidth = 1920; - appHeight = 1080; - qCDebug(boot2QtDemos) << "Using MEDIUM UI variant"; -#elif defined(UI_LARGE) - mainFile = QStringLiteral("qrc:/resources/large/MainLarge.qml"); - styleFile = QUrl("qrc:/resources/large/StyleLarge.qml"); - uiVariant = "large"; - fullScreen = true; - appWidth = 3840; - appHeight = 2160; - qCDebug(boot2QtDemos) << "Using LARGE UI variant"; -#else -#error "Unknown UI form factor set in the project file" -#endif + mainFile = namingScheme + QStringLiteral("/resources/small/MainSmall.qml"); + styleFile = namingScheme + QStringLiteral("/resources/small/StyleSmall.qml"); + + uiVariant = "small"; + fullScreen = false; + appWidth = 1920; + appHeight = 1080; qmlRegisterSingletonType(styleFile, "Style", 1,0, "Style"); @@ -221,12 +166,14 @@ int main(int argc, char *argv[]) if (fullScreen) item->showFullScreen(); - item->setProperty("dataProviderPool", QVariant::fromValue(dataProviderPool)); + item->setProperty("localProviderPool", QVariant::fromValue(localProviderPool)); + item->setProperty("remoteProviderPool", QVariant::fromValue(remoteProviderPool)); item->setProperty("contentFile", mainFile); item->setProperty("seriesStorage", QVariant::fromValue(&seriesStorage)); item->setProperty("addresses", addressString); } int returnValue = app.exec(); - dataProviderPool->stopScanning(); + remoteProviderPool->stopScanning(); + return returnValue; } diff --git a/tradeshow/iot-sensortag/mockdataprovider.cpp b/tradeshow/iot-sensortag/mockdataprovider.cpp index 7e9607c..d8eb309 100644 --- a/tradeshow/iot-sensortag/mockdataprovider.cpp +++ b/tradeshow/iot-sensortag/mockdataprovider.cpp @@ -47,22 +47,23 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include "mockdataprovider.h" #include #define MOCK_DATA_SLOW_REFRESH_INTERVAL_MS 1000 #define MOCK_DATA_RAPID_REFRESH_INTERVAL_MS 200 -MockDataProvider::MockDataProvider(QString id, QObject* parent) - : SensorTagDataProvider(id, parent), - xAxisG(-0.02f), - yAxisG(0.0f), - zAxisG(0.02f), - luxIncrease(100), - rotationDegPerSecXIncrease(5), - rotationDegPerSecYIncrease(7), - rotationDegPerSecZIncrease(-9), - m_smaSamples(0) +MockDataProvider::MockDataProvider(QString id, QObject *parent) + : SensorTagDataProvider(id, parent) + , xAxisG(-0.02f) + , yAxisG(0.0f) + , zAxisG(0.02f) + , luxIncrease(100) + , rotationDegPerSecXIncrease(5) + , rotationDegPerSecYIncrease(7) + , rotationDegPerSecZIncrease(-9) + , m_smaSamples(0) { intervalRotation = MOCK_DATA_RAPID_REFRESH_INTERVAL_MS; humidity = 40; @@ -81,21 +82,22 @@ MockDataProvider::MockDataProvider(QString id, QObject* parent) bool MockDataProvider::startDataFetching() { // Mock data is immediately available - m_state = Connected; + setState(Connected); qsrand(QDateTime::currentMSecsSinceEpoch() / 1000); - slowUpdateTimer = new QTimer(this); - connect(slowUpdateTimer, SIGNAL(timeout()), this, SLOT(slowTimerExpired())); - slowUpdateTimer->start(MOCK_DATA_SLOW_REFRESH_INTERVAL_MS); - rapidUpdateTimer = new QTimer(this); - connect(rapidUpdateTimer, SIGNAL(timeout()), this, SLOT(rapidTimerExpired())); - rapidUpdateTimer->start(MOCK_DATA_RAPID_REFRESH_INTERVAL_MS); + connect(&slowUpdateTimer, &QTimer::timeout, + this, &MockDataProvider::slowTimerExpired, Qt::UniqueConnection); + slowUpdateTimer.start(MOCK_DATA_SLOW_REFRESH_INTERVAL_MS); + connect(&rapidUpdateTimer, &QTimer::timeout, + this, &MockDataProvider::rapidTimerExpired, Qt::UniqueConnection); + rapidUpdateTimer.start(MOCK_DATA_RAPID_REFRESH_INTERVAL_MS); return true; } void MockDataProvider::endDataFetching() { - slowUpdateTimer->stop(); + slowUpdateTimer.stop(); + rapidUpdateTimer.stop(); } QString MockDataProvider::sensorType() const @@ -235,7 +237,6 @@ void MockDataProvider::rapidTimerExpired() void MockDataProvider::startServiceScan() { - } void MockDataProvider::reset() diff --git a/tradeshow/iot-sensortag/mockdataprovider.h b/tradeshow/iot-sensortag/mockdataprovider.h index 3555428..361db2e 100644 --- a/tradeshow/iot-sensortag/mockdataprovider.h +++ b/tradeshow/iot-sensortag/mockdataprovider.h @@ -49,7 +49,9 @@ ****************************************************************************/ #ifndef MOCKDATAPROVIDER_H #define MOCKDATAPROVIDER_H + #include "sensortagdataprovider.h" + #include #include #include @@ -58,7 +60,7 @@ class MockDataProvider : public SensorTagDataProvider { Q_OBJECT public: - explicit MockDataProvider(QString id, QObject* parent = 0); + explicit MockDataProvider(QString id, QObject *parent = 0); bool startDataFetching(); void endDataFetching(); @@ -75,8 +77,8 @@ protected: void reset() override; private: - QTimer *slowUpdateTimer; - QTimer *rapidUpdateTimer; + QTimer slowUpdateTimer; + QTimer rapidUpdateTimer; float xAxisG; float yAxisG; float zAxisG; diff --git a/tradeshow/iot-sensortag/mockdataproviderpool.cpp b/tradeshow/iot-sensortag/mockdataproviderpool.cpp index 758cd99..5f37737 100644 --- a/tradeshow/iot-sensortag/mockdataproviderpool.cpp +++ b/tradeshow/iot-sensortag/mockdataproviderpool.cpp @@ -71,10 +71,9 @@ void MockDataProviderPool::startScanning() p = new MockDataProvider("MOCK_PROVIDER_3", this); p->setTagType(SensorTagDataProvider::Magnetometer | SensorTagDataProvider::AirPressure); m_dataProviders.push_back(p); - for (int i=0; i < m_dataProviders.length(); i++) { - m_dataProviders.at(i)->startDataFetching(); + for (int i=0; i < m_dataProviders.length(); i++) emit providerConnected(p->id()); - } + // Stop scanning as we already have a provider finishScanning(); } diff --git a/tradeshow/iot-sensortag/mockdataproviderpool.h b/tradeshow/iot-sensortag/mockdataproviderpool.h index ba91d6c..5f47ff5 100644 --- a/tradeshow/iot-sensortag/mockdataproviderpool.h +++ b/tradeshow/iot-sensortag/mockdataproviderpool.h @@ -60,13 +60,13 @@ public: void startScanning() override; - SensorTagDataProvider* providerForCloud() const override; + SensorTagDataProvider *providerForCloud() const override; protected: void finishScanning(); private: - SensorTagDataProvider* m_cloudProvider; + SensorTagDataProvider *m_cloudProvider; }; #endif // MOCKDATAPROVIDERPOOL_H diff --git a/tradeshow/iot-sensortag/mqttdataprovider.h b/tradeshow/iot-sensortag/mqttdataprovider.h new file mode 100644 index 0000000..9a52332 --- /dev/null +++ b/tradeshow/iot-sensortag/mqttdataprovider.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef MQTTDATAPROVIDER_H +#define MQTTDATAPROVIDER_H + +#include "sensortagdataprovider.h" +#include +#include +#include +#include + +class QTimer; + +class MqttDataProvider : public SensorTagDataProvider +{ + Q_OBJECT +public: + explicit MqttDataProvider(QString id, QMqttClient *client, QObject *parent = 0); + + bool startDataFetching(); + void endDataFetching(); + QString sensorType() const; + QString versionString() const; + void reset() override; + +public slots: + void messageReceived(const QMqttMessage &msg); + void parseMessage(const QString &content, const QString &topic); + void dataTimeout(); + +private: + QTimer *m_pollTimer; + QMqttClient *m_client; + QMqttSubscription *m_subscription; +}; +#endif // MQTTDATAPROVIDER_H diff --git a/tradeshow/iot-sensortag/mqttdataproviderpool.h b/tradeshow/iot-sensortag/mqttdataproviderpool.h new file mode 100644 index 0000000..bcd29c6 --- /dev/null +++ b/tradeshow/iot-sensortag/mqttdataproviderpool.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef MQTTDATAPROVIDERPOOL_H +#define MQTTDATAPROVIDERPOOL_H + +#include "dataproviderpool.h" +#include + +class MqttDataProvider; + +class MqttDataProviderPool : public DataProviderPool +{ +public: + explicit MqttDataProviderPool(QObject *parent = 0); + + void startScanning() override; + +public Q_SLOTS: + void deviceUpdate(const QMqttMessage &msg); + +private: + QMqttClient *m_client; +}; + +#endif // MQTTDATAPROVIDERPOOL_H diff --git a/tradeshow/iot-sensortag/resources/base/BaseChart.qml b/tradeshow/iot-sensortag/resources/base/BaseChart.qml index d144916..7c846a5 100644 --- a/tradeshow/iot-sensortag/resources/base/BaseChart.qml +++ b/tradeshow/iot-sensortag/resources/base/BaseChart.qml @@ -54,7 +54,7 @@ import SensorTag.DataProvider 1.0 Item { id: baseChart - property var sensor: null + property var sensor: singleSensorSource property string title property alias contentItem: loader.item property alias content: loader.sourceComponent diff --git a/tradeshow/iot-sensortag/resources/base/GyroChart.qml b/tradeshow/iot-sensortag/resources/base/GyroChart.qml index 78ee163..63a9122 100644 --- a/tradeshow/iot-sensortag/resources/base/GyroChart.qml +++ b/tradeshow/iot-sensortag/resources/base/GyroChart.qml @@ -92,7 +92,6 @@ BaseChart { anchors.left: parent.left anchors.leftMargin: -20 anchors.right: parent.right - anchors.rightMargin: -15 antialiasing: true backgroundColor: "transparent" legend.visible: false diff --git a/tradeshow/iot-sensortag/resources/base/HumidityChart.qml b/tradeshow/iot-sensortag/resources/base/HumidityChart.qml index 60d1ee7..582128f 100644 --- a/tradeshow/iot-sensortag/resources/base/HumidityChart.qml +++ b/tradeshow/iot-sensortag/resources/base/HumidityChart.qml @@ -48,8 +48,6 @@ ** ****************************************************************************/ import QtQuick 2.5 -import QtQuick.Controls 2.0 -import QtQuick.Controls.Styles 1.4 import QtCharts 2.1 import SensorTag.DataProvider 1.0 import QtQuick.Extras 1.4 diff --git a/tradeshow/iot-sensortag/resources/base/MagnetometerChart.qml b/tradeshow/iot-sensortag/resources/base/MagnetometerChart.qml index cf4a409..6f0d3c7 100644 --- a/tradeshow/iot-sensortag/resources/base/MagnetometerChart.qml +++ b/tradeshow/iot-sensortag/resources/base/MagnetometerChart.qml @@ -57,7 +57,6 @@ BaseChart { property int maxNumOfMagnReadings: 24 - readonly property color chartColor: "#15bdff" readonly property string xColor: "#4db300" readonly property string yColor: "white" readonly property string zColor: "#f64405" diff --git a/tradeshow/iot-sensortag/resources/base/RotationPage.qml b/tradeshow/iot-sensortag/resources/base/RotationPage.qml index eee47c1..a153c80 100644 --- a/tradeshow/iot-sensortag/resources/base/RotationPage.qml +++ b/tradeshow/iot-sensortag/resources/base/RotationPage.qml @@ -53,7 +53,7 @@ import SensorTag.DataProvider 1.0 Item { id: dialerRoot - property var sensor + property var sensor : singleSensorSource property var rotationUpdateInterval: sensor ? sensor.rotationUpdateInterval : 0 property int sensorState: sensor ? sensor.state : SensorTagData.Disconnected diff --git a/tradeshow/iot-sensortag/resources/base/SensorSettings.qml b/tradeshow/iot-sensortag/resources/base/SensorSettings.qml index c9c326a..7661325 100644 --- a/tradeshow/iot-sensortag/resources/base/SensorSettings.qml +++ b/tradeshow/iot-sensortag/resources/base/SensorSettings.qml @@ -53,152 +53,156 @@ import Style 1.0 import SensorTag.DataProvider 1.0 Rectangle { - id: mainRect + id: sourceSelector + property alias sensorCount : sensorListView.count + property color selectedBackgroundColor : "#15bdff" + property color deselectedBackgroundColor: "transparent" - property alias listModelCount: list.count + color: "transparent" + width: 800 + height: 800 + anchors.horizontalCenter: parent.horizontalCenter - width: 620 - height: 480 - color: "black" + Image { + source: "images/bg_blue.jpg" + anchors.fill: parent + } - Text { - id: titleText - color: "white" - text: "SENSOR SETTINGS" - font.pixelSize: Style.indicatorTitleFontSize - anchors.horizontalCenter: parent.horizontalCenter + Image { + id: separator + source: pathPrefix + "General/separator.png" anchors.top: parent.top - anchors.topMargin: 8 + width: parent.width + transform: Rotation { + origin.x: separator.width / 2 + origin.y: separator.height / 2 + angle: 180 + } } - Image { - id: icon + Rectangle { + id: buttonRect + anchors.top: separator.bottom + anchors.margins: 20 + color: "transparent" + width: parent.width - 20 + height: 40 + + Rectangle { + border.color: "white" + color: localSelected ? sourceSelector.selectedBackgroundColor : sourceSelector.deselectedBackgroundColor + anchors.top: parent.top + anchors.left: parent.left + width: parent.width / 2 + height: 30 + Text { + text: "Local" + anchors.centerIn: parent + color: "white" + font.pixelSize: 26 + } + } - anchors.top: titleText.bottom - anchors.horizontalCenter: parent.horizontalCenter - anchors.margins: 8 - source: pathPrefix + "Toolbar/icon_topbar_sensor.png" + Rectangle { + border.color: "white" + color: !localSelected ? sourceSelector.selectedBackgroundColor : sourceSelector.deselectedBackgroundColor + anchors.top: parent.top + anchors.right: parent.right + width: parent.width / 2 + height: 30 + Text { + text: "Remote" + anchors.centerIn: parent + color: "white" + font.pixelSize: 26 + } + } + + MouseArea { + anchors.fill: parent + onClicked: localSelected = !localSelected + } } ListView { - id: list - anchors.top: icon.bottom - anchors.topMargin: 16 - anchors.left: parent.left - anchors.leftMargin: 30 - anchors.right: parent.right - anchors.rightMargin: 30 - orientation: ListView.Horizontal - model: dataProviderPool.dataProviders - height: parent.height + id: sensorListView + model: localSelected ? (localProviderPool ? localProviderPool.dataProviders : 0) + : (remoteProviderPool ? remoteProviderPool.dataProviders : 0) + + width: buttonRect.width + anchors.top: buttonRect.bottom + anchors.bottom: connectButton.top + focus: true clip: true - snapMode: ListView.SnapToItem - boundsBehavior: Flickable.StopAtBounds - - function getTagTypeStr(tagType) { - var tagStr = ""; - if (tagType & SensorTagData.AmbientTemperature) - tagStr += "Ambient Temperature\n"; - if (tagType & SensorTagData.ObjectTemperature) - tagStr += "Object Temperature\n"; - if (tagType & SensorTagData.Humidity) - tagStr += "Humidity\n"; - if (tagType & SensorTagData.Altitude) - tagStr += "Altitude\n"; - if (tagType & SensorTagData.Light) - tagStr += "Light\n"; - if (tagType & SensorTagData.Rotation) - tagStr += "Gyroscope\n"; - if (tagType & SensorTagData.Magnetometer) - tagStr += "Magnetometer\n"; - if (tagType & SensorTagData.Accelometer) - tagStr += "Accelometer\n"; - - return tagStr; - } - delegate: Item { - id: listItem - width: mainRect.width / 3 - height: childrenRect.height - - ColumnLayout { - spacing: 8 - - Text { - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - horizontalAlignment: Text.AlignHCenter - text: providerId - color: "white" - font.pixelSize: 16 - elide: Text.ElideMiddle - } - - BlinkingIcon { - id: sensorIcon - - property bool canBlink: modelData.state === SensorTagData.Scanning - - onCanBlinkChanged: { - if (canBlink) - sensorIcon.startBlinking(); - else - sensorIcon.stopBlinking(); - } - - source: pathPrefix + "Toolbar/icon_topbar_sensor.png" - anchors.horizontalCenter: parent.horizontalCenter - - Component.onDestruction: { - sensorIcon.stopBlinking() - } - - MouseArea { - anchors.fill: parent - onClicked: { - if (modelData.state === SensorTagData.Connected) - dataProviderPool.disconnectProvider(modelData.providerId); - else if (modelData.state === SensorTagData.NotFound) - dataProviderPool.startScanning(); - else if (modelData.state === SensorTagData.Scanning) - dataProviderPool.disconnectProvider(modelData.providerId) - else - modelData.startServiceScan(); - } - } - } + delegate: Rectangle { + border.color: "white" + color: ListView.isCurrentItem ? sourceSelector.selectedBackgroundColor + : sourceSelector.deselectedBackgroundColor + radius: 5 + height: 30 + width: parent.width + Text { + text: providerId + anchors.centerIn: parent + color: "white" + font.pixelSize: 26 + } + MouseArea { + anchors.fill: parent + onClicked: sensorListView.currentIndex = index + } + } + } - Text { - Layout.alignment: Qt.AlignHCenter - text: modelData.state === SensorTagData.NotFound ? "\nNOT FOUND" - : (modelData.state === SensorTagData.Disconnected) ? "\nDISCONNECTED" - : (modelData.state === SensorTagData.Scanning) ? "\nCONNECTING" - : (modelData.state === SensorTagData.Connected) ? "\nCONNECTED" - : "Error" - color: "white" - font.pixelSize: 14 + Rectangle { + id: connectButton + width: buttonRect.width / 2 + height: 30 + anchors.bottom: bottomSeparator.top + anchors.right: parent.right + color: sensorListView.currentIndex != -1 ? sourceSelector.selectedBackgroundColor : "transparent" + border.color: "white" + Text { + text: "Connect" + anchors.centerIn: parent + color: "white" + font.pixelSize: 26 + } + MouseArea { + id: connectButtonArea + anchors.fill: parent + enabled: sensorListView.currentIndex != -1 + onClicked: { + clickBait.deactivate() + + var currentPool = getCurrentPool(); + if (currentPool.dataProviders[sensorListView.currentIndex] === singleSensorSource) { + console.log("Same data provider selected, nothing to change...") + return; } - Item { - height: 30 - width: 10 - } + if (singleSensorSource) + singleSensorSource.endDataFetching(); + // UI gets information about the intended setup of the + // sensor even though they have not been really discovered yet + if (currentPool) { + singleSensorSource = currentPool.dataProviders[sensorListView.currentIndex] + currentPool.currentProviderIndex = sensorListView.currentIndex - Text { - color: "white" - text: "Provides data for:" - font.pixelSize: 14 - } + seriesStorage.setDataProviderPool(currentPool); + seriesStorage.dataProviderPoolChanged(); - Text { - color: "white" - lineHeight: 0.7 - text: list.getTagTypeStr(modelData.tagType()) - font.pixelSize: 14 + singleSensorSource.startDataFetching() } } } } + + Image { + id: bottomSeparator + source: pathPrefix + "General/separator.png" + anchors.bottom: parent.bottom + width: parent.width + } } diff --git a/tradeshow/iot-sensortag/resources/base/TopToolbar.qml b/tradeshow/iot-sensortag/resources/base/TopToolbar.qml index fd5054d..0d15ce1 100644 --- a/tradeshow/iot-sensortag/resources/base/TopToolbar.qml +++ b/tradeshow/iot-sensortag/resources/base/TopToolbar.qml @@ -57,63 +57,22 @@ Item { height: 100 width: implicitWidth - CloudSettings { - id: cloudSettings - - x: cloudItem.x - y: topToolbar.height - visible: false - } - SensorSettings { id: sensorList x: sensorItem.x y: topToolbar.height - visible: false - } - - Item { - id: cloudItem - - height: topToolbar.height - anchors.top: parent.top - anchors.left: parent.left - anchors.leftMargin: 8 - width: icon.width + cloudText.width + 3 * anchors.leftMargin - opacity: dataProviderPool.name === "Cloud" || dataProviderPool.name === "Demo" ? 1.0 : 0.0 - - Image { - id: icon - width: 58 - height: 40 - anchors.top: parent.top - anchors.margins: 8 - source: pathPrefix + "Toolbar/icon_topbar_cloud.png" - } - - Text { - id: cloudText - color: "white" - text: "CLOUD" - width: contentWidth - font.pixelSize: Style.topToolbarSmallFontSize - anchors.verticalCenter: icon.verticalCenter - anchors.left: icon.right - anchors.margins: 8 - } - - MouseArea { - anchors.fill: parent - onClicked: clickBait.activate(cloudSettings) - } + width: Math.min(mainWindow.width, 800) + height: mainWindow.height - topToolbar.height + visible: true } Item { id: sensorItem height: topToolbar.height anchors.top: parent.top - anchors.left: cloudItem.right + anchors.left: parent.left //cloudItem.right + anchors.leftMargin: 8 width: sensorIcon.width + sensorButton.width + 3 * anchors.leftMargin Image { @@ -127,7 +86,7 @@ Item { Text { anchors.centerIn: parent - text: sensorList.listModelCount + text: sensorList.sensorCount color: "white" font.pixelSize: Style.topToolbarSmallFontSize } @@ -233,4 +192,6 @@ Item { deactivate(); } } + + Component.onCompleted: clickBait.activate(sensorList) } diff --git a/tradeshow/iot-sensortag/resources/base/main.qml b/tradeshow/iot-sensortag/resources/base/main.qml index 6d492d5..caa8617 100644 --- a/tradeshow/iot-sensortag/resources/base/main.qml +++ b/tradeshow/iot-sensortag/resources/base/main.qml @@ -55,11 +55,21 @@ import SensorTag.SeriesStorage 1.0 Window { id: mainWindow + property var singleSensorSource : null property alias contentFile: contentLoader.source - property DataProviderPool dataProviderPool + property DataProviderPool localProviderPool + property DataProviderPool remoteProviderPool property SeriesStorage seriesStorage property real globalBlinkOpacity: 1.0 property string addresses : "" + property bool localSelected : true + + function getCurrentPool() { + if (localSelected) + return localProviderPool + else + return remoteProviderPool + } // Size defaults to the small display width: 1920 @@ -74,13 +84,11 @@ Window { Loader { id: contentLoader - + visible: true anchors.fill: parent anchors.centerIn: parent } - - function startBlink() { flash.blinkers++; } diff --git a/tradeshow/iot-sensortag/resources/large/MainLarge.qml b/tradeshow/iot-sensortag/resources/large/MainLarge.qml deleted file mode 100644 index d855c0e..0000000 --- a/tradeshow/iot-sensortag/resources/large/MainLarge.qml +++ /dev/null @@ -1,177 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of Qt for Device Creation. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -import QtQuick 2.6 -import SensorTag.DataProvider 1.0 -import "../base" - -Item { - id: main - - width: 1920 - height: 1080 - - Component.onCompleted: { - dataProviderPool.startScanning() - } - - Connections { - target: dataProviderPool - onScanFinished: { - ambientTemp.sensor = dataProviderPool.getProvider(SensorTagData.AmbientTemperature); - objectTemp.sensor = dataProviderPool.getProvider(SensorTagData.ObjectTemperature); - humidity.sensor = dataProviderPool.getProvider(SensorTagData.Humidity); - //airPressure.sensor = dataProviderPool.getProvider(SensorTagData.AirPressure); - light.sensor = dataProviderPool.getProvider(SensorTagData.Light); - magnetometer.sensor = dataProviderPool.getProvider(SensorTagData.Magnetometer); - rotation.sensor = dataProviderPool.getProvider(SensorTagData.Rotation); - } - } - - Column { - id: leftPane - - property int indicatorHeight: height / 4 - spacing - - anchors.left: parent.left - anchors.leftMargin: 8 - anchors.top: main.top - anchors.bottom: main.bottom - width: 360 - spacing: 16 - - TemperatureChart { - id: ambientTemp - - width: leftPane.width - height: leftPane.indicatorHeight - } - - ObjectTemperatureChart { - id: objectTemp - - width: leftPane.width - height: leftPane.indicatorHeight - } - - HumidityChart { - id: humidity - - width: leftPane.width - height: leftPane.indicatorHeight - } - -// AirPressureChart { -// id: airPressure - -// width: leftPane.width -// height: leftPane.indicatorHeight -// } - } - - Column { - id: rightPane - - anchors.right: parent.right - anchors.rightMargin: 8 - anchors.top: main.top - anchors.bottom: main.bottom - width: 360 - spacing: 16 - - LightChart { - id: light - - width: rightPane.width - height: leftPane.height / 4 - } - - MagnetometerChart { - id: magnetometer - - width: rightPane.width - height: leftPane.height / 4 - } - - GyroPage { - id: rotation - - width: rightPane.width - height: leftPane.height / 4 - onClicked: mainContainer.source = "../base/GyroPage.qml" - } - } - - Loader { - id: mainContainer - - anchors.top: topToolbar.bottom - anchors.left: leftPane.right - anchors.leftMargin: 32 - anchors.right: rightPane.left - anchors.rightMargin: 32 - anchors.bottom: bottomToolbar.top - } - - TopToolbar { - id: topToolbar - - anchors.left: leftPane.right - anchors.right: rightPane.left - } - - BottomToolbar { - id: bottomToolbar - - anchors.left: leftPane.right - anchors.right: rightPane.left - anchors.bottom: main.bottom - height: 30 - } -} diff --git a/tradeshow/iot-sensortag/resources/large/StyleLarge.qml b/tradeshow/iot-sensortag/resources/large/StyleLarge.qml deleted file mode 100644 index e4d439d..0000000 --- a/tradeshow/iot-sensortag/resources/large/StyleLarge.qml +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of Qt for Device Creation. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -pragma Singleton -import QtQuick 2.0 - -QtObject { - property int indicatorTitleFontSize: 22 - property int indicatorTitleSize: 41 - - property int topToolbarSmallFontSize: 20 - property int topToolbarLargeFontSize: 62 -} diff --git a/tradeshow/iot-sensortag/resources/large/images/AirPressure/AirPre_base_gauge.png b/tradeshow/iot-sensortag/resources/large/images/AirPressure/AirPre_base_gauge.png deleted file mode 100644 index 30a24b8..0000000 Binary files a/tradeshow/iot-sensortag/resources/large/images/AirPressure/AirPre_base_gauge.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/large/images/AmbientTemperature/ambTemp_display_amb.png b/tradeshow/iot-sensortag/resources/large/images/AmbientTemperature/ambTemp_display_amb.png deleted file mode 100644 index 5a4bcf0..0000000 Binary files a/tradeshow/iot-sensortag/resources/large/images/AmbientTemperature/ambTemp_display_amb.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/large/images/General/icon_sensor.png b/tradeshow/iot-sensortag/resources/large/images/General/icon_sensor.png deleted file mode 100644 index 8157ef7..0000000 Binary files a/tradeshow/iot-sensortag/resources/large/images/General/icon_sensor.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/large/images/General/separator.png b/tradeshow/iot-sensortag/resources/large/images/General/separator.png deleted file mode 100644 index 4dae4f8..0000000 Binary files a/tradeshow/iot-sensortag/resources/large/images/General/separator.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_base_gauge.png b/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_base_gauge.png deleted file mode 100644 index 0d0331c..0000000 Binary files a/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_base_gauge.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_max_hum.png b/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_max_hum.png deleted file mode 100644 index 381c4dd..0000000 Binary files a/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_max_hum.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_min_hum.png b/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_min_hum.png deleted file mode 100644 index c3f9442..0000000 Binary files a/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_min_hum.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/large/images/Light/light_base_gauge.png b/tradeshow/iot-sensortag/resources/large/images/Light/light_base_gauge.png deleted file mode 100644 index 6a68729..0000000 Binary files a/tradeshow/iot-sensortag/resources/large/images/Light/light_base_gauge.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/large/images/Light/light_brightness.png b/tradeshow/iot-sensortag/resources/large/images/Light/light_brightness.png deleted file mode 100644 index 45b1e2b..0000000 Binary files a/tradeshow/iot-sensortag/resources/large/images/Light/light_brightness.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/large/images/ObjectTemperature/objTemp_base_circle.png b/tradeshow/iot-sensortag/resources/large/images/ObjectTemperature/objTemp_base_circle.png deleted file mode 100644 index a506d2a..0000000 Binary files a/tradeshow/iot-sensortag/resources/large/images/ObjectTemperature/objTemp_base_circle.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/large/images/ObjectTemperature/objTemp_display_obj.png b/tradeshow/iot-sensortag/resources/large/images/ObjectTemperature/objTemp_display_obj.png deleted file mode 100644 index bc320ac..0000000 Binary files a/tradeshow/iot-sensortag/resources/large/images/ObjectTemperature/objTemp_display_obj.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/medium/MainMedium.qml b/tradeshow/iot-sensortag/resources/medium/MainMedium.qml deleted file mode 100644 index d855c0e..0000000 --- a/tradeshow/iot-sensortag/resources/medium/MainMedium.qml +++ /dev/null @@ -1,177 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of Qt for Device Creation. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -import QtQuick 2.6 -import SensorTag.DataProvider 1.0 -import "../base" - -Item { - id: main - - width: 1920 - height: 1080 - - Component.onCompleted: { - dataProviderPool.startScanning() - } - - Connections { - target: dataProviderPool - onScanFinished: { - ambientTemp.sensor = dataProviderPool.getProvider(SensorTagData.AmbientTemperature); - objectTemp.sensor = dataProviderPool.getProvider(SensorTagData.ObjectTemperature); - humidity.sensor = dataProviderPool.getProvider(SensorTagData.Humidity); - //airPressure.sensor = dataProviderPool.getProvider(SensorTagData.AirPressure); - light.sensor = dataProviderPool.getProvider(SensorTagData.Light); - magnetometer.sensor = dataProviderPool.getProvider(SensorTagData.Magnetometer); - rotation.sensor = dataProviderPool.getProvider(SensorTagData.Rotation); - } - } - - Column { - id: leftPane - - property int indicatorHeight: height / 4 - spacing - - anchors.left: parent.left - anchors.leftMargin: 8 - anchors.top: main.top - anchors.bottom: main.bottom - width: 360 - spacing: 16 - - TemperatureChart { - id: ambientTemp - - width: leftPane.width - height: leftPane.indicatorHeight - } - - ObjectTemperatureChart { - id: objectTemp - - width: leftPane.width - height: leftPane.indicatorHeight - } - - HumidityChart { - id: humidity - - width: leftPane.width - height: leftPane.indicatorHeight - } - -// AirPressureChart { -// id: airPressure - -// width: leftPane.width -// height: leftPane.indicatorHeight -// } - } - - Column { - id: rightPane - - anchors.right: parent.right - anchors.rightMargin: 8 - anchors.top: main.top - anchors.bottom: main.bottom - width: 360 - spacing: 16 - - LightChart { - id: light - - width: rightPane.width - height: leftPane.height / 4 - } - - MagnetometerChart { - id: magnetometer - - width: rightPane.width - height: leftPane.height / 4 - } - - GyroPage { - id: rotation - - width: rightPane.width - height: leftPane.height / 4 - onClicked: mainContainer.source = "../base/GyroPage.qml" - } - } - - Loader { - id: mainContainer - - anchors.top: topToolbar.bottom - anchors.left: leftPane.right - anchors.leftMargin: 32 - anchors.right: rightPane.left - anchors.rightMargin: 32 - anchors.bottom: bottomToolbar.top - } - - TopToolbar { - id: topToolbar - - anchors.left: leftPane.right - anchors.right: rightPane.left - } - - BottomToolbar { - id: bottomToolbar - - anchors.left: leftPane.right - anchors.right: rightPane.left - anchors.bottom: main.bottom - height: 30 - } -} diff --git a/tradeshow/iot-sensortag/resources/medium/StyleMedium.qml b/tradeshow/iot-sensortag/resources/medium/StyleMedium.qml deleted file mode 100644 index e4d439d..0000000 --- a/tradeshow/iot-sensortag/resources/medium/StyleMedium.qml +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the examples of Qt for Device Creation. -** -** $QT_BEGIN_LICENSE:BSD$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** BSD License Usage -** Alternatively, you may use this file under the terms of the BSD license -** as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -pragma Singleton -import QtQuick 2.0 - -QtObject { - property int indicatorTitleFontSize: 22 - property int indicatorTitleSize: 41 - - property int topToolbarSmallFontSize: 20 - property int topToolbarLargeFontSize: 62 -} diff --git a/tradeshow/iot-sensortag/resources/medium/images/AirPressure/AirPre_base_gauge.png b/tradeshow/iot-sensortag/resources/medium/images/AirPressure/AirPre_base_gauge.png deleted file mode 100644 index 2f1d658..0000000 Binary files a/tradeshow/iot-sensortag/resources/medium/images/AirPressure/AirPre_base_gauge.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/medium/images/AmbientTemperature/ambTemp_display_amb.png b/tradeshow/iot-sensortag/resources/medium/images/AmbientTemperature/ambTemp_display_amb.png deleted file mode 100644 index cad440a..0000000 Binary files a/tradeshow/iot-sensortag/resources/medium/images/AmbientTemperature/ambTemp_display_amb.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/medium/images/General/icon_sensor.png b/tradeshow/iot-sensortag/resources/medium/images/General/icon_sensor.png deleted file mode 100644 index 49cc090..0000000 Binary files a/tradeshow/iot-sensortag/resources/medium/images/General/icon_sensor.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/medium/images/General/separator.png b/tradeshow/iot-sensortag/resources/medium/images/General/separator.png deleted file mode 100644 index dbd25a4..0000000 Binary files a/tradeshow/iot-sensortag/resources/medium/images/General/separator.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_base_gauge.png b/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_base_gauge.png deleted file mode 100644 index 494a0e6..0000000 Binary files a/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_base_gauge.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_max_hum.png b/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_max_hum.png deleted file mode 100644 index c4a7d7b..0000000 Binary files a/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_max_hum.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_min_hum.png b/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_min_hum.png deleted file mode 100644 index 75b83d1..0000000 Binary files a/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_min_hum.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/medium/images/Light/light_base_gauge.png b/tradeshow/iot-sensortag/resources/medium/images/Light/light_base_gauge.png deleted file mode 100644 index 9c66fbb..0000000 Binary files a/tradeshow/iot-sensortag/resources/medium/images/Light/light_base_gauge.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/medium/images/Light/light_brightness.png b/tradeshow/iot-sensortag/resources/medium/images/Light/light_brightness.png deleted file mode 100644 index fc8e82a..0000000 Binary files a/tradeshow/iot-sensortag/resources/medium/images/Light/light_brightness.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/medium/images/ObjectTemperature/objTemp_base_circle.png b/tradeshow/iot-sensortag/resources/medium/images/ObjectTemperature/objTemp_base_circle.png deleted file mode 100644 index 86c966f..0000000 Binary files a/tradeshow/iot-sensortag/resources/medium/images/ObjectTemperature/objTemp_base_circle.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/medium/images/ObjectTemperature/objTemp_display_obj.png b/tradeshow/iot-sensortag/resources/medium/images/ObjectTemperature/objTemp_display_obj.png deleted file mode 100644 index 77d53f3..0000000 Binary files a/tradeshow/iot-sensortag/resources/medium/images/ObjectTemperature/objTemp_display_obj.png and /dev/null differ diff --git a/tradeshow/iot-sensortag/resources/small/MainSmall.qml b/tradeshow/iot-sensortag/resources/small/MainSmall.qml index 83835e3..7528b6b 100644 --- a/tradeshow/iot-sensortag/resources/small/MainSmall.qml +++ b/tradeshow/iot-sensortag/resources/small/MainSmall.qml @@ -55,30 +55,20 @@ Item { id: main function startRescan(sensor) { - if (sensor.state === SensorTagData.NotFound) - dataProviderPool.startScanning(); - else if (sensor.state === SensorTagData.Scanning) - dataProviderPool.disconnectProvider(sensor.providerId) - else if (sensor.state !== SensorTagData.Connected) - sensor.startServiceScan(); + // ### Only do this magic when a local device is connected +// if (sensor.state === SensorTagData.NotFound) +// dataProviderPool.startScanning(); +// else if (sensor.state === SensorTagData.Scanning) +// dataProviderPool.disconnectProvider(sensor.providerId) +// else if (sensor.state !== SensorTagData.Connected) +// sensor.startServiceScan(); } anchors.fill: parent Component.onCompleted: { - dataProviderPool.startScanning(); - - // UI gets information about the intended setup of the - // sensor even though they have not been really discovered yet - ambientTemp.sensor = dataProviderPool.getProvider(SensorTagData.AmbientTemperature); - objectTemp.sensor = dataProviderPool.getProvider(SensorTagData.ObjectTemperature); - humidity.sensor = dataProviderPool.getProvider(SensorTagData.Humidity); - airPressure.sensor = dataProviderPool.getProvider(SensorTagData.AirPressure); - light.sensor = dataProviderPool.getProvider(SensorTagData.Light); - magnetometer.sensor = dataProviderPool.getProvider(SensorTagData.Magnetometer); - rotation.sensor = dataProviderPool.getProvider(SensorTagData.Rotation); - accelometer.sensor = dataProviderPool.getProvider(SensorTagData.Accelometer); - rotationMain.sensor = dataProviderPool.getProvider(SensorTagData.Rotation); + localProviderPool.startScanning(); + remoteProviderPool.startScanning(); } Column { @@ -172,6 +162,7 @@ Item { RotationPage { id: rotationMain + visible: main.width > (leftPane.width + rightPane.width + 800) anchors.top: topToolbar.bottom anchors.left: leftPane.right anchors.leftMargin: 32 diff --git a/tradeshow/iot-sensortag/sensortagdataprovider.cpp b/tradeshow/iot-sensortag/sensortagdataprovider.cpp index f5defa3..409b95a 100644 --- a/tradeshow/iot-sensortag/sensortagdataprovider.cpp +++ b/tradeshow/iot-sensortag/sensortagdataprovider.cpp @@ -47,6 +47,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include "sensortagdataprovider.h" #include @@ -72,36 +73,35 @@ SensorTagDataProvider::SensorTagDataProvider(QObject *parent) : QObject(parent) , pressureAtZeroAltitude(AIR_PRESSURE_P0) { - } -SensorTagDataProvider::SensorTagDataProvider(QString id, QObject* parent) - : QObject(parent), - humidity(0), - irAmbientTemperature(0), - irObjectTemperature(0), - lightIntensityLux(0), - barometerCelsiusTemperature(0), - barometerTemperatureAverage(25), - barometerHPa(0), - gyroscopeX_degPerSec(0), - gyroscopeY_degPerSec(0), - gyroscopeZ_degPerSec(0), - accelometerX(0), - accelometerY(0), - accelometerZ(0), +SensorTagDataProvider::SensorTagDataProvider(QString id, QObject *parent) + : QObject(parent) + , humidity(0) + , irAmbientTemperature(0) + , irObjectTemperature(0) + , lightIntensityLux(0) + , barometerCelsiusTemperature(0) + , barometerTemperatureAverage(25) + , barometerHPa(0) + , gyroscopeX_degPerSec(0) + , gyroscopeY_degPerSec(0) + , gyroscopeZ_degPerSec(0) + , accelometerX(0) + , accelometerY(0) + , accelometerZ(0) /* Object is not "walking in the air" so have one axis at 1G */ - magnetometerMicroT_xAxis(-1), - magnetometerMicroT_yAxis(0), - magnetometerMicroT_zAxis(0), - rotation_x(0), - rotation_y(0), - rotation_z(0), - intervalRotation(DEFAULT_REFRESH_INTERVAL_MS), - altitude(0), - m_tagType(AmbientTemperature | ObjectTemperature | Humidity | AirPressure | Light | Magnetometer | Rotation | Accelometer | Altitude), - m_id(id), - m_state(NotFound) + , magnetometerMicroT_xAxis(-1) + , magnetometerMicroT_yAxis(0) + , magnetometerMicroT_zAxis(0) + , rotation_x(0) + , rotation_y(0) + , rotation_z(0) + , intervalRotation(DEFAULT_REFRESH_INTERVAL_MS) + , altitude(0) + , m_tagType(AmbientTemperature | ObjectTemperature | Humidity | AirPressure | Light | Magnetometer | Rotation | Accelometer | Altitude) + , m_id(id) + , m_state(NotFound) { } diff --git a/tradeshow/iot-sensortag/sensortagdataprovider.h b/tradeshow/iot-sensortag/sensortagdataprovider.h index 523bd93..f3a6dcb 100644 --- a/tradeshow/iot-sensortag/sensortagdataprovider.h +++ b/tradeshow/iot-sensortag/sensortagdataprovider.h @@ -49,6 +49,7 @@ ****************************************************************************/ #ifndef SENSORTAGDATAPROVIDER_H #define SENSORTAGDATAPROVIDER_H + #include #include #include @@ -100,13 +101,19 @@ public: Altitude = 1 << 8 }; static const int tagTypeCount = 9; - enum ProviderState {NotFound = 0, Disconnected, Scanning, Connected, Error}; + enum ProviderState { + NotFound = 0, + Disconnected, + Scanning, + Connected, + Error + }; explicit SensorTagDataProvider(QObject *parent = 0); SensorTagDataProvider(QString id, QObject *parent = 0); - virtual bool startDataFetching() {return false;} - virtual void endDataFetching() {} + Q_INVOKABLE virtual bool startDataFetching() {return false;} + Q_INVOKABLE virtual void endDataFetching() {} QString getRelativeHumidityString() const; virtual double getRelativeHumidity() const; virtual double getInfraredAmbientTemperature() const; @@ -176,7 +183,6 @@ protected: double barometerCelsiusTemperature; double barometerTemperatureAverage; double barometerHPa; - //double temperatureAverage; float gyroscopeX_degPerSec; float gyroscopeY_degPerSec; float gyroscopeZ_degPerSec; diff --git a/tradeshow/iot-sensortag/sensortagdataproviderpool.cpp b/tradeshow/iot-sensortag/sensortagdataproviderpool.cpp index 987e8b3..3b66d90 100644 --- a/tradeshow/iot-sensortag/sensortagdataproviderpool.cpp +++ b/tradeshow/iot-sensortag/sensortagdataproviderpool.cpp @@ -58,22 +58,23 @@ Q_DECLARE_LOGGING_CATEGORY(boot2QtDemos) SensorTagDataProviderPool::SensorTagDataProviderPool(QObject *parent) : SensorTagDataProviderPool("SensorTag", parent) { - } -SensorTagDataProviderPool::SensorTagDataProviderPool(QString poolName, QObject* parent) +SensorTagDataProviderPool::SensorTagDataProviderPool(QString poolName, QObject *parent) : DataProviderPool(poolName, parent) { m_discoveryAgent = new QBluetoothDeviceDiscoveryAgent(); - connect(m_discoveryAgent, SIGNAL(deviceDiscovered(const QBluetoothDeviceInfo&)), - this, SLOT(btDeviceFound(const QBluetoothDeviceInfo&))); - connect(m_discoveryAgent, SIGNAL(error(QBluetoothDeviceDiscoveryAgent::Error)), - this, SLOT(deviceScanError(QBluetoothDeviceDiscoveryAgent::Error))); - connect(m_discoveryAgent, SIGNAL(finished()), this, SLOT(deviceDiscoveryFinished())); + connect(m_discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, + this, &SensorTagDataProviderPool::btDeviceFound); + connect(m_discoveryAgent, QOverload::of(&QBluetoothDeviceDiscoveryAgent::error), + this, &SensorTagDataProviderPool::deviceScanError); + connect(m_discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, + this, &SensorTagDataProviderPool::deviceDiscoveryFinished); } void SensorTagDataProviderPool::startScanning() { + m_discoveryAgent->setLowEnergyDiscoveryTimeout(0); m_discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); if (m_discoveryAgent->isActive()) { @@ -81,7 +82,7 @@ void SensorTagDataProviderPool::startScanning() } } -void SensorTagDataProviderPool::disconnectProvider(QString id) +void SensorTagDataProviderPool::disconnectProvider(const QString &id) { SensorTagDataProvider *p = findProvider(id); if (BluetoothDataProvider *btp = qobject_cast(findProvider(id))) @@ -90,21 +91,6 @@ void SensorTagDataProviderPool::disconnectProvider(QString id) p->setState(SensorTagDataProvider::Disconnected); } -void SensorTagDataProviderPool::setMacFilterList(const QStringList &addressList) -{ - m_macFilters = addressList; -} - -QStringList SensorTagDataProviderPool::macFilters() const -{ - return m_macFilters; -} - -void SensorTagDataProviderPool::setnameFilteList(const QStringList &nameList) -{ - m_nameFilters = nameList; -} - SensorTagDataProvider *SensorTagDataProviderPool::providerForCloud() const { return m_providerForCloud; @@ -136,40 +122,27 @@ void SensorTagDataProviderPool::finishScanning() void SensorTagDataProviderPool::btDeviceFound(const QBluetoothDeviceInfo &info) { if (info.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) { - bool filtered = m_macFilters.length() || m_nameFilters.length(); - bool found = filtered ? false : true; - - if (m_macFilters.length() && m_macFilters.contains(info.address().toString())) - found = true; - else if (m_nameFilters.length() && m_nameFilters.contains(info.name())) - found = true; - - if (found) { - BluetoothDataProvider *dataProvider = static_cast(findProvider(info.address().toString())); - if (!dataProvider) { - qCDebug(boot2QtDemos) << "Found a new Sensor tag. Name:" << info.name() << ", addr:" << info.address().toString() ; - dataProvider = new BluetoothDataProvider(info.address().toString(), this); - m_dataProviders.append(dataProvider); - emit dataProvidersChanged(); - } - if (!dataProvider->device()) { - qCDebug(boot2QtDemos) << "Attach BluetoothDevice info for an existing Sensor Tag:" << info.name(); - BluetoothDevice *d = new BluetoothDevice(info); - dataProvider->bindToDevice(d); - connect(dataProvider, &SensorTagDataProvider::stateChanged, this, &SensorTagDataProviderPool::handleStateChange); - dataProvider->startDataFetching(); - } - else if (dataProvider->state() != SensorTagDataProvider::Connected) { - qCDebug(boot2QtDemos) << "Start service scan for already attached Sensor Tag" << dataProvider->id(); - dataProvider->startServiceScan(); - } + // all tags by TI have this naming convention + if (info.name().contains(QLatin1String("SensorTag")) && !m_knownDevices.contains(info)) { + qCDebug(boot2QtDemos) << "Found a new device:" << info.name(); + m_knownDevices.append(info); + BluetoothDataProvider *p = new BluetoothDataProvider(info, this); + m_dataProviders.push_back(p); + connect(p, &SensorTagDataProvider::stateChanged, + this, &SensorTagDataProviderPool::handleStateChange); + + emit dataProvidersChanged(); + + // Set initial state to Scanning for UI to be + // able to show "Connecting.." information + p->setState(SensorTagDataProvider::Scanning); } } } void SensorTagDataProviderPool::handleStateChange() { - SensorTagDataProvider *provider = static_cast(sender()); + SensorTagDataProvider *provider = static_cast(sender()); switch (provider->state()) { case SensorTagDataProvider::Disconnected: @@ -200,7 +173,7 @@ void SensorTagDataProviderPool::deviceScanError(QBluetoothDeviceDiscoveryAgent:: emit scanFinished(); } -SensorTagDataProvider* SensorTagDataProviderPool::findProvider(QString id) const +SensorTagDataProvider *SensorTagDataProviderPool::findProvider(QString id) const { for (SensorTagDataProvider *p : m_dataProviders) { if (id == p->id()) diff --git a/tradeshow/iot-sensortag/sensortagdataproviderpool.h b/tradeshow/iot-sensortag/sensortagdataproviderpool.h index fe8b30f..6353d24 100644 --- a/tradeshow/iot-sensortag/sensortagdataproviderpool.h +++ b/tradeshow/iot-sensortag/sensortagdataproviderpool.h @@ -66,23 +66,15 @@ public: explicit SensorTagDataProviderPool(QObject *parent = 0); void startScanning() override; - void disconnectProvider(QString id) override; + void disconnectProvider(const QString &id) override; - // setMacFilterList takes presence over name filter - Q_INVOKABLE void setMacFilterList(const QStringList& addressList); - QStringList macFilters() const; - Q_INVOKABLE void setnameFilteList(const QStringList& nameList); - - SensorTagDataProvider* providerForCloud() const override; + SensorTagDataProvider *providerForCloud() const override; protected: SensorTagDataProviderPool(QString poolName, QObject *parent = 0); virtual void finishScanning(); void updateProviderForCloud(); - QStringList m_macFilters; - QStringList m_nameFilters; - private slots: void deviceDiscoveryFinished(); void btDeviceFound(const QBluetoothDeviceInfo &info); @@ -93,6 +85,7 @@ private: SensorTagDataProvider *findProvider(QString id) const; QBluetoothDeviceDiscoveryAgent *m_discoveryAgent; + QList m_knownDevices; SensorTagDataProvider *m_providerForCloud; }; diff --git a/tradeshow/iot-sensortag/seriesstorage.cpp b/tradeshow/iot-sensortag/seriesstorage.cpp index 556499c..5c032d8 100644 --- a/tradeshow/iot-sensortag/seriesstorage.cpp +++ b/tradeshow/iot-sensortag/seriesstorage.cpp @@ -47,6 +47,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ + #include "seriesstorage.h" Q_DECLARE_METATYPE(QAbstractSeries *) @@ -70,7 +71,7 @@ void SeriesStorage::setDataProviderPool(DataProviderPool *pool) m_providerPool = pool; if (!m_providerPool) return; - connect(m_providerPool, &DataProviderPool::dataProvidersChanged, this, &SeriesStorage::dataProviderPoolChanged); + connect(m_providerPool, &DataProviderPool::currentProviderIndexChanged, this, &SeriesStorage::dataProviderPoolChanged); } void SeriesStorage::setTemperatureSeries(QAbstractSeries *series) @@ -94,20 +95,20 @@ void SeriesStorage::setMagnetoMeterSeries(QAbstractSeries *xSeries, QAbstractSer void SeriesStorage::dataProviderPoolChanged() { - m_gyroProvider = m_providerPool->getProvider(SensorTagDataProvider::Rotation); - if (m_gyroProvider) { - connect(m_gyroProvider, &SensorTagDataProvider::rotationValuesChanged, this, &SeriesStorage::changeRotationSeries); - } - - m_magnetoProvider = m_providerPool->getProvider(SensorTagDataProvider::Magnetometer); - if (m_magnetoProvider) { - connect(m_magnetoProvider, &SensorTagDataProvider::magnetometerMicroTChanged, this, &SeriesStorage::changeMagnetoSeries); - } - - m_temperatureProvider = m_providerPool->getProvider(SensorTagDataProvider::AmbientTemperature); - if (m_temperatureProvider) { - connect(m_temperatureProvider, &SensorTagDataProvider::infraredAmbientTemperatureChanged, this, &SeriesStorage::changeTemperatureSeries); - } + m_gyroProvider = m_providerPool->currentProvider(); + if (m_gyroProvider) + connect(m_gyroProvider, &SensorTagDataProvider::rotationValuesChanged, + this, &SeriesStorage::changeRotationSeries, Qt::UniqueConnection); + + m_magnetoProvider = m_providerPool->currentProvider(); + if (m_magnetoProvider) + connect(m_magnetoProvider, &SensorTagDataProvider::magnetometerMicroTChanged, + this, &SeriesStorage::changeMagnetoSeries, Qt::UniqueConnection); + + m_temperatureProvider = m_providerPool->currentProvider(); + if (m_temperatureProvider) + connect(m_temperatureProvider, &SensorTagDataProvider::infraredAmbientTemperatureChanged, + this, &SeriesStorage::changeTemperatureSeries, Qt::UniqueConnection); } void SeriesStorage::changeRotationSeries() @@ -146,11 +147,14 @@ void SeriesStorage::changeMagnetoSeries() static int axisMin = 0; static int axisMax = maxMagneticReadings; - updatePoints(m_magnetoListX, magneticSeriesIndex, m_magnetoProvider->getMagnetometerMicroT_xAxis(), maxMagneticReadings); + updatePoints(m_magnetoListX, magneticSeriesIndex, + m_magnetoProvider->getMagnetometerMicroT_xAxis(), maxMagneticReadings); m_magnetoX->replace(m_magnetoListX); - updatePoints(m_magnetoListY, magneticSeriesIndex, m_magnetoProvider->getMagnetometerMicroT_yAxis(), maxMagneticReadings); + updatePoints(m_magnetoListY, magneticSeriesIndex, + m_magnetoProvider->getMagnetometerMicroT_yAxis(), maxMagneticReadings); m_magnetoY->replace(m_magnetoListY); - updatePoints(m_magnetoListZ, magneticSeriesIndex, m_magnetoProvider->getMagnetometerMicroT_zAxis(), maxMagneticReadings); + updatePoints(m_magnetoListZ, magneticSeriesIndex, + m_magnetoProvider->getMagnetometerMicroT_zAxis(), maxMagneticReadings); m_magnetoZ->replace(m_magnetoListZ); if (magneticSeriesIndex >= maxMagneticReadings) { @@ -174,7 +178,7 @@ void SeriesStorage::changeTemperatureSeries() static const int defaultAvgValue = 25; m_temperatureList.removeLast(); - m_temperatureList.append(QPointF(temperatureSeriesIndex -1, m_temperatureProvider->getInfraredAmbientTemperature())); + m_temperatureList.append(QPointF(temperatureSeriesIndex - 1, m_temperatureProvider->getInfraredAmbientTemperature())); m_temperatureList.append(QPointF(temperatureSeriesIndex, defaultAvgValue)); if (m_temperatureList.size() >= maxTemperatureReadings) diff --git a/tradeshow/iot-sensortag/seriesstorage.h b/tradeshow/iot-sensortag/seriesstorage.h index 94447c3..5bc40bb 100644 --- a/tradeshow/iot-sensortag/seriesstorage.h +++ b/tradeshow/iot-sensortag/seriesstorage.h @@ -63,7 +63,7 @@ class SeriesStorage : public QObject public: explicit SeriesStorage(QObject *parent = nullptr); - void setDataProviderPool(DataProviderPool *pool); + Q_INVOKABLE void setDataProviderPool(DataProviderPool *pool); Q_INVOKABLE void setTemperatureSeries(QAbstractSeries *series); Q_INVOKABLE void setGyroSeries(QAbstractSeries *xSeries, QAbstractSeries *ySeries, QAbstractSeries *zSeries); diff --git a/tradeshow/iot-sensortag/uilarge.qrc b/tradeshow/iot-sensortag/uilarge.qrc deleted file mode 100644 index 6885e21..0000000 --- a/tradeshow/iot-sensortag/uilarge.qrc +++ /dev/null @@ -1,17 +0,0 @@ - - - resources/large/MainLarge.qml - resources/large/StyleLarge.qml - resources/large/images/General/icon_sensor.png - resources/large/images/General/separator.png - resources/large/images/AmbientTemperature/ambTemp_display_amb.png - resources/large/images/Humidity/humidity_base_gauge.png - resources/large/images/Humidity/humidity_max_hum.png - resources/large/images/Humidity/humidity_min_hum.png - resources/large/images/ObjectTemperature/objTemp_base_circle.png - resources/large/images/ObjectTemperature/objTemp_display_obj.png - resources/large/images/Light/light_base_gauge.png - resources/large/images/Light/light_brightness.png - resources/large/images/AirPressure/AirPre_base_gauge.png - - diff --git a/tradeshow/iot-sensortag/uimedium.qrc b/tradeshow/iot-sensortag/uimedium.qrc deleted file mode 100644 index bb4324c..0000000 --- a/tradeshow/iot-sensortag/uimedium.qrc +++ /dev/null @@ -1,17 +0,0 @@ - - - resources/medium/MainMedium.qml - resources/medium/StyleMedium.qml - resources/medium/images/AmbientTemperature/ambTemp_display_amb.png - resources/medium/images/General/icon_sensor.png - resources/medium/images/General/separator.png - resources/medium/images/Humidity/humidity_max_hum.png - resources/medium/images/Humidity/humidity_min_hum.png - resources/medium/images/Humidity/humidity_base_gauge.png - resources/medium/images/ObjectTemperature/objTemp_base_circle.png - resources/medium/images/ObjectTemperature/objTemp_display_obj.png - resources/medium/images/Light/light_base_gauge.png - resources/medium/images/Light/light_brightness.png - resources/medium/images/AirPressure/AirPre_base_gauge.png - - -- cgit v1.2.3 From bb226a8dc9b6508c8d72c67b5260b9a733f7fca1 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 20 Sep 2017 09:37:05 +0200 Subject: iot-sensortag: Add support for MQTT Using MQTT a sensor can send its data to a broker as well as display data from a remote MQTT broker. Change-Id: I01f961e89b2c6d028498ce61e4087a47742b8b82 Reviewed-by: Maurice Kalinowski --- tradeshow/iot-sensortag/SensorTagDemo.pro | 77 +++-- tradeshow/iot-sensortag/main.cpp | 29 +- tradeshow/iot-sensortag/mqttdataprovider.cpp | 214 +++++++++++++ tradeshow/iot-sensortag/mqttdataproviderpool.cpp | 123 ++++++++ tradeshow/iot-sensortag/mqttdataproviderpool.h | 5 + tradeshow/iot-sensortag/mqttupdate.cpp | 371 +++++++++++++++++++++++ tradeshow/iot-sensortag/mqttupdate.h | 121 ++++++++ 7 files changed, 891 insertions(+), 49 deletions(-) create mode 100644 tradeshow/iot-sensortag/mqttdataprovider.cpp create mode 100644 tradeshow/iot-sensortag/mqttdataproviderpool.cpp create mode 100644 tradeshow/iot-sensortag/mqttupdate.cpp create mode 100644 tradeshow/iot-sensortag/mqttupdate.h (limited to 'tradeshow') diff --git a/tradeshow/iot-sensortag/SensorTagDemo.pro b/tradeshow/iot-sensortag/SensorTagDemo.pro index bd79351..c69a181 100644 --- a/tradeshow/iot-sensortag/SensorTagDemo.pro +++ b/tradeshow/iot-sensortag/SensorTagDemo.pro @@ -1,7 +1,15 @@ TEMPLATE = app -QT += 3dcore 3drender 3dinput 3dquick 3dlogic core gui qml quick 3dquickextras widgets -QT += bluetooth network charts +QT += \ + bluetooth \ + core \ + charts \ + gui \ + network \ + qml \ + quick \ + widgets + CONFIG += c++11 DEFINES += QT_NO_FOREACH @@ -9,25 +17,17 @@ DEFINES += QT_NO_FOREACH # Needed at least for RPi3 and iMX #CONFIG += DEPLOY_TO_FS -# Uncomment DEVICE_TYPE and assign either UI_SMALL, UI_MEDIUM, UI_LARGE -# to force using that UI form factor. Otherwise -# the form factor is determined based on the platform -DEVICE_TYPE = UI_SMALL - -# If DEVICE_TYPE is not set manually, try to determine -# the correct device type by the used operating system -win32|linux:!android:!qnx { +win32|linux|android:!qnx { CONFIG += BLUETOOTH_HOST - isEmpty(DEVICE_TYPE) { DEVICE_TYPE = UI_SMALL } -} else:android { - isEmpty(DEVICE_TYPE) { DEVICE_TYPE = UI_MEDIUM } - ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android-sources - QMAKE_CXX_FLAGS -= -DQT_OPENGL_FORCE_SHADER_DEFINES -} else:ios { - isEmpty(DEVICE_TYPE) { DEVICE_TYPE = UI_MEDIUM } +} else { + message(Unsupported target platform) } -win32 { +# For using MQTT upload enable this config. +# This enables both, host and client mode +CONFIG += UPDATE_TO_MQTT_BROKER + +win32:!contains(CONFIG, UPDATE_TO_MQTT_BROKER) { WASTORAGE_PATH = $$(WASTORAGE_LOCATION) isEmpty(WASTORAGE_PATH): message("Location for Azure Storage libs unknown. Please specify WASTORAGE_LOCATION") CPPRESTSDK_PATH = $$(CPPRESTSDK_LOCATION) @@ -83,6 +83,21 @@ BLUETOOTH_HOST { bluetoothdevice.h } +UPDATE_TO_MQTT_BROKER { + CONFIG -= UPDATE_TO_AZURE + + !qtHaveModule(mqtt): error("Could not find MQTT module for Qt version") + QT += mqtt + DEFINES += MQTT_UPLOAD + + SOURCES += mqttupdate.cpp \ + mqttdataproviderpool.cpp \ + mqttdataprovider.cpp + HEADERS += mqttupdate.h \ + mqttdataproviderpool.h \ + mqttdataprovider.h +} + UPDATE_TO_AZURE { SOURCES += cloudupdate.cpp HEADERS += cloudupdate.h @@ -100,29 +115,9 @@ UPDATE_TO_AZURE { RESOURCES += base.qrc -equals(DEVICE_TYPE, "UI_SMALL") { - DEFINES += UI_SMALL - !DEPLOY_TO_FS: RESOURCES += uismall.qrc - uiVariant.files = resources/small - uiVariant.path = /opt/$${TARGET}/resources - message("Resource file for SMALL display picked") -} - -equals(DEVICE_TYPE, "UI_MEDIUM") { - DEFINES += UI_MEDIUM - !DEPLOY_TO_FS: RESOURCES += uimedium.qrc - uiVariant.files = resources/medium - uiVariant.path = /opt/$${TARGET}/resources - message("Resource file for MEDIUM display picked") -} - -equals(DEVICE_TYPE, "UI_LARGE") { - DEFINES += UI_LARGE - !DEPLOY_TO_FS: RESOURCES += uilarge.qrc - uiVariant.files = resources/large - uiVariant.path = /opt/$${TARGET}/resources - message("Resource file for LARGE display picked") -} +!DEPLOY_TO_FS: RESOURCES += uismall.qrc +uiVariant.files = resources/small +uiVariant.path = /opt/$${TARGET}/resources # Additional import path used to resolve QML modules in Qt Creator's code model QML_IMPORT_PATH = diff --git a/tradeshow/iot-sensortag/main.cpp b/tradeshow/iot-sensortag/main.cpp index 30c8813..555d1a8 100644 --- a/tradeshow/iot-sensortag/main.cpp +++ b/tradeshow/iot-sensortag/main.cpp @@ -47,13 +47,6 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include -#include -#include -#include -#include -#include -#include #if defined(RUNS_AS_HOST) #include "bluetoothdataprovider.h" @@ -67,9 +60,21 @@ #include "mockdataproviderpool.h" #ifdef AZURE_UPLOAD #include "cloudupdate.h" +#elif defined (MQTT_UPLOAD) +#include "mqttupdate.h" +#include "mqttdataprovider.h" +#include "mqttdataproviderpool.h" #endif #include "seriesstorage.h" +#include +#include +#include +#include +#include +#include +#include + Q_DECLARE_LOGGING_CATEGORY(boot2QtDemos) Q_LOGGING_CATEGORY(boot2QtDemos, "boot2qt.demos.iot") @@ -90,6 +95,9 @@ int main(int argc, char *argv[]) parser.addHelpOption(); parser.process(app); +#if defined(MQTT_UPLOAD) + remoteProviderPool = new MqttDataProviderPool; +#endif #if defined(RUNS_AS_HOST) // localProviderPool = new MockDataProviderPool; localProviderPool = new DemoDataProviderPool; @@ -100,8 +108,13 @@ int main(int argc, char *argv[]) qmlRegisterType("SensorTag.DataProvider", 1, 0, "DataProviderPool"); qmlRegisterType("SensorTag.SeriesStorage", 1, 0, "SeriesStorage"); -#if defined(RUNS_AS_HOST) && defined(AZURE_UPLOAD) +#if defined(RUNS_AS_HOST) && (defined(AZURE_UPLOAD) || defined(MQTT_UPLOAD)) +#if AZURE_UPLOAD CloudUpdate update; +# else + MqttUpdate update; +# endif + update.setDataProviderPool(localProviderPool); update.restart(); #endif diff --git a/tradeshow/iot-sensortag/mqttdataprovider.cpp b/tradeshow/iot-sensortag/mqttdataprovider.cpp new file mode 100644 index 0000000..8985f02 --- /dev/null +++ b/tradeshow/iot-sensortag/mqttdataprovider.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mqttdataprovider.h" + +#include +#include +#include + +#define MAJOR_VERSION_NUMBER 1 +#define MINOR_VERSION_NUMBER 0 + +Q_DECLARE_LOGGING_CATEGORY(boot2QtDemos) + +MqttDataProvider::MqttDataProvider(QString id, QMqttClient *client, QObject *parent) + : SensorTagDataProvider(id, parent) + , m_client(client) + , m_subscription(nullptr) +{ + intervalRotation = 200; + + m_pollTimer = new QTimer(this); + m_pollTimer->setInterval(intervalRotation); + m_pollTimer->setSingleShot(false); + connect(m_pollTimer, &QTimer::timeout, this, &MqttDataProvider::dataTimeout); +} + +bool MqttDataProvider::startDataFetching() +{ + const QString subName = QString::fromLocal8Bit("sensors/%1/#").arg(m_id); + + m_subscription = m_client->subscribe(subName); + connect(m_subscription, &QMqttSubscription::messageReceived, + this, &MqttDataProvider::messageReceived); + return true; +} + +void MqttDataProvider::endDataFetching() +{ + if (m_subscription) { + disconnect(m_subscription, &QMqttSubscription::messageReceived, + this, &MqttDataProvider::messageReceived); + m_subscription->unsubscribe(); + m_subscription = nullptr; + } +} + +QString MqttDataProvider::sensorType() const +{ + return QString("mqtt data"); +} + +QString MqttDataProvider::versionString() const +{ + return QString::number(MAJOR_VERSION_NUMBER) + "." + QString::number(MINOR_VERSION_NUMBER); +} + +void MqttDataProvider::reset() +{ +} + +void MqttDataProvider::messageReceived(const QMqttMessage &msg) +{ + parseMessage(msg.payload(), msg.topic()); + if (!m_pollTimer->isActive()) + m_pollTimer->start(); +} + +void MqttDataProvider::parseMessage(const QString &content, const QString &topic) +{ + const QString msgType = topic.split(QLatin1Char('/')).last(); + if (msgType == QStringLiteral("type")) { + qDebug() << "Type: " << content; + } else if (msgType == QStringLiteral("version")) { + qDebug() << "Version: " << content; + } else if (msgType == QStringLiteral("humid")) { + bool ok; + const double v = content.toDouble(&ok); + if (ok) + humidity = v; + } else if (msgType == QStringLiteral("light")) { + bool ok; + const double v = content.toDouble(&ok); + if (ok) + lightIntensityLux = v; + } else if (msgType == QStringLiteral("temperature")) { + //ambient_object + QString streamContent = content; + QTextStream stream(&streamContent); + double ambient, object; + char c; + stream >> ambient >> c >> object; + + irAmbientTemperature = ambient; + irObjectTemperature = object; + } else if (msgType == QStringLiteral("barometer")) { + QString streamContent = content; + QTextStream stream(&streamContent); + double v1, v2; + char c; + stream >> v1 >> c >> v2; + barometerCelsiusTemperature = v1; + barometerHPa = v2; + } else if (msgType == QStringLiteral("gyro")) { + QString streamContent = content; + QTextStream stream(&streamContent); + double v1, v2, v3; + char c; + stream >> v1 >> c >> v2 >> c >> v3; + gyroscopeX_degPerSec = v1; + gyroscopeY_degPerSec = v2; + gyroscopeZ_degPerSec = v3; + } else if (msgType == QStringLiteral("accel")) { + QString streamContent = content; + QTextStream stream(&streamContent); + double v1, v2, v3; + char c; + stream >> v1 >> c >> v2 >> c >> v3; + accelometerX = v1; + accelometerY = v2; + accelometerZ = v3; + } else if (msgType == QStringLiteral("magnet")) { + QString streamContent = content; + QTextStream stream(&streamContent); + double v1, v2, v3; + char c; + stream >> v1 >> c >> v2 >> c >> v3; + magnetometerMicroT_xAxis = v1; + magnetometerMicroT_yAxis = v2; + magnetometerMicroT_zAxis = v3; + } else if (msgType == QStringLiteral("rotation")) { + QString streamContent = content; + QTextStream stream(&streamContent); + double v1, v2, v3; + char c; + stream >> v1 >> c >> v2 >> c >> v3; + rotation_x = v1; + rotation_y = v2; + rotation_z = v3; + } else if (msgType == QStringLiteral("altitude")) { + QString streamContent = content; + QTextStream stream(&streamContent); + float alt; + stream >> alt; + altitude = alt; + } else { + qWarning() << "Unknown sensor data received:" << topic; + } +} + +void MqttDataProvider::dataTimeout() +{ + emit relativeHumidityChanged(); + emit lightIntensityChanged(); + emit infraredAmbientTemperatureChanged(); + emit infraredObjectTemperatureChanged(); + emit barometerCelsiusTemperatureChanged(); + emit barometer_hPaChanged(); + emit gyroscopeDegPerSecChanged(); + emit accelometerChanged(); + emit magnetometerMicroTChanged(); + emit rotationXChanged(); + emit rotationYChanged(); + emit rotationZChanged(); + emit altitudeChanged(); + emit rotationValuesChanged(); +} diff --git a/tradeshow/iot-sensortag/mqttdataproviderpool.cpp b/tradeshow/iot-sensortag/mqttdataproviderpool.cpp new file mode 100644 index 0000000..24ce47c --- /dev/null +++ b/tradeshow/iot-sensortag/mqttdataproviderpool.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mqttdataproviderpool.h" +#include "mqttdataprovider.h" + +#include + +MqttDataProviderPool::MqttDataProviderPool(QObject *parent) + : DataProviderPool(parent) + , m_client(new QMqttClient(this)) +{ + m_poolName = "Mqtt"; +} + +void MqttDataProviderPool::startScanning() +{ + emit providerConnected("MQTT_CLOUD"); + emit providersUpdated(); + emit dataProvidersChanged(); + + m_client->setHostname(QLatin1String(MQTT_BROKER)); + m_client->setPort(MQTT_PORT); + m_client->setUsername(QByteArray(MQTT_USERNAME)); + m_client->setPassword(QByteArray(MQTT_PASSWORD)); + + connect(m_client, &QMqttClient::connected, [this]() { + auto sub = m_client->subscribe(QLatin1String("sensors/active")); + connect(sub, &QMqttSubscription::messageReceived, this, &MqttDataProviderPool::deviceUpdate); + }); + connect(m_client, &QMqttClient::disconnected, [this]() { + qDebug() << "Pool client disconnected"; + }); + m_client->connectToHost(); +} + +void MqttDataProviderPool::deviceUpdate(const QMqttMessage &msg) +{ + static QSet knownDevices; + // Registration is: deviceName>Online + const QByteArrayList payload = msg.payload().split('>'); + const QString deviceName = payload.first(); + const QString deviceStatus = payload.at(1); + const QString subName = QString::fromLocal8Bit("sensors/%1/#").arg(deviceName); + + bool updateRequired = false; + if (deviceStatus == QLatin1String("Online")) { // new device + // Skip local items + if (deviceName.startsWith(QSysInfo::machineHostName())) + return; + + if (!knownDevices.contains(deviceName)) { + auto prov = new MqttDataProvider(deviceName, m_client, this); + prov->setState(SensorTagDataProvider::Connected); + m_dataProviders.push_back(prov); + if (m_currentProvider == nullptr) + setCurrentProviderIndex(m_dataProviders.size() - 1); + knownDevices.insert(deviceName); + updateRequired = true; + } + } else if (deviceStatus == QLatin1String("Offline")) { // device died + knownDevices.remove(deviceName); + updateRequired = true; + for (auto prov : m_dataProviders) { + if (prov->id() == deviceName) { + m_dataProviders.removeAll(prov); + break; + } + } + } + + if (updateRequired) { + emit providersUpdated(); + emit dataProvidersChanged(); + } +} diff --git a/tradeshow/iot-sensortag/mqttdataproviderpool.h b/tradeshow/iot-sensortag/mqttdataproviderpool.h index bcd29c6..1ba33ff 100644 --- a/tradeshow/iot-sensortag/mqttdataproviderpool.h +++ b/tradeshow/iot-sensortag/mqttdataproviderpool.h @@ -55,6 +55,11 @@ class MqttDataProvider; +#define MQTT_BROKER "" +#define MQTT_PORT 1883 +#define MQTT_USERNAME "" +#define MQTT_PASSWORD "" + class MqttDataProviderPool : public DataProviderPool { public: diff --git a/tradeshow/iot-sensortag/mqttupdate.cpp b/tradeshow/iot-sensortag/mqttupdate.cpp new file mode 100644 index 0000000..f574965 --- /dev/null +++ b/tradeshow/iot-sensortag/mqttupdate.cpp @@ -0,0 +1,371 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mqttupdate.h" +#include "cloudservice.h" +#include "dataproviderpool.h" +#include "sensortagdataprovider.h" +#include "demodataproviderpool.h" +#include "mqttdataproviderpool.h" + +#include +#include + +#define ROUNDING_DECIMALS 2 +#define UPDATE_INTERVAL 100 + +Q_DECLARE_LOGGING_CATEGORY(boot2QtDemos) + +MqttUpdate::MqttUpdate(QObject *parent) + : QObject(parent) + , m_providerPool(0) +#ifdef MQTT_TIMER_BASED_PUBLISH + , m_timerId(0) +#endif + , m_handler(nullptr) + , m_updateInterval(UPDATE_INTERVAL) +{ +} + +void MqttUpdate::setDataProviderPool(DataProviderPool *provider) +{ + m_providerPool = provider; + connect(m_providerPool, &DataProviderPool::currentProviderChanged, this, [=]() { + if (m_handler) + m_handler->deleteLater(); + + SensorTagDataProvider *provider = m_providerPool->currentProvider(); + if (!provider) + return; + + const QString hostname = QSysInfo::machineHostName(); + + m_handler = new MqttEventHandler(hostname + QLatin1String(" - ") + provider->id()); + m_handler->m_providerPool = m_providerPool; + + connect(provider, &SensorTagDataProvider::gyroscopeDegPerSecChanged, m_handler, &MqttEventHandler::uploadGyro); + connect(provider, &SensorTagDataProvider::accelometerChanged, m_handler, &MqttEventHandler::uploadAccelerometer); + connect(provider, &SensorTagDataProvider::rotationXChanged, m_handler, &MqttEventHandler::uploadRotation); + connect(provider, &SensorTagDataProvider::infraredAmbientTemperatureChanged, m_handler, &MqttEventHandler::uploadTemperature); + connect(provider, &SensorTagDataProvider::magnetometerMicroTChanged, m_handler, &MqttEventHandler::uploadMagnetometer); + connect(provider, &SensorTagDataProvider::relativeHumidityChanged, m_handler, &MqttEventHandler::uploadHumidity); + connect(provider, &SensorTagDataProvider::lightIntensityChanged, m_handler, &MqttEventHandler::uploadLight); + connect(provider, &SensorTagDataProvider::barometer_hPaChanged, m_handler, &MqttEventHandler::uploadBarometer); + connect(provider, &SensorTagDataProvider::altitudeChanged, m_handler, &MqttEventHandler::uploadAltitude); + }); +} + +int MqttUpdate::updateInterval() const +{ + return m_updateInterval; +} + +void MqttUpdate::setUpdateInterval(int interval) +{ + m_updateInterval = interval; +} + +void MqttUpdate::restart() +{ +#ifdef MQTT_TIMER_BASED_PUBLISH + killTimer(m_timerId); + m_timerId = startTimer(m_updateInterval); +#endif +} + +void MqttUpdate::stop() +{ +#ifdef MQTT_TIMER_BASED_PUBLISH + killTimer(m_timerId); +#endif +} + +#ifndef MQTT_TIMER_BASED_PUBLISH + +inline bool ensureConnected(QMqttClient *client) +{ + if (client->state() == QMqttClient::Connected) + return true; + + if (client->state() == QMqttClient::Disconnected) { + qCDebug(boot2QtDemos) << "Disconnected, need to reconnect"; + client->connectToHost(); + } + + return false; // Connecting, nothing to do +} + +void MqttEventHandler::uploadGyro() +{ + if (!ensureConnected(m_client)) + return; + SensorTagDataProvider *provider = m_providerPool->currentProvider(); + + if (provider) { + const QString gyro = QString("%1_%2_%3").arg(provider->getGyroscopeX_degPerSec(), 0, 'f', ROUNDING_DECIMALS) + .arg(provider->getGyroscopeY_degPerSec(), 0, 'f', ROUNDING_DECIMALS) + .arg(provider->getGyroscopeZ_degPerSec(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("gyro"), gyro.toLocal8Bit()); + } +} + +void MqttEventHandler::uploadTemperature() +{ + if (!ensureConnected(m_client)) + return; + + SensorTagDataProvider *provider = m_providerPool->currentProvider(); + + if (provider) { + const QString temperature = QString("%1_%2").arg(provider->getInfraredAmbientTemperature(), 0, 'f', ROUNDING_DECIMALS) + .arg(provider->getInfraredObjectTemperature(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("temperature"), temperature.toLocal8Bit()); + } +} + +void MqttEventHandler::uploadHumidity() +{ + if (!ensureConnected(m_client)) + return; + + SensorTagDataProvider *provider = m_providerPool->currentProvider(); + + if (provider) + m_client->publish(m_topicPrefix + QLatin1String("humid"), + QString("%1").arg(provider->getRelativeHumidity(), 0, 'f', ROUNDING_DECIMALS).toLocal8Bit()); +} + +void MqttEventHandler::uploadLight() +{ + if (!ensureConnected(m_client)) + return; + + SensorTagDataProvider *provider = m_providerPool->currentProvider(); + + if (provider) + m_client->publish(m_topicPrefix + QLatin1String("light"), + QString("%1").arg(provider->getLightIntensityLux(), 0, 'f', ROUNDING_DECIMALS).toLocal8Bit()); +} + +void MqttEventHandler::uploadAltitude() +{ + if (!ensureConnected(m_client)) + return; + + SensorTagDataProvider *provider = m_providerPool->currentProvider(); + + if (provider) + m_client->publish(m_topicPrefix + QLatin1String("altitude"), + QString("%1").arg(provider->getAltitude(), 0, 'f', ROUNDING_DECIMALS).toLocal8Bit()); +} + +void MqttEventHandler::uploadBarometer() +{ + if (!ensureConnected(m_client)) + return; + + SensorTagDataProvider *provider = m_providerPool->currentProvider(); + + if (provider) { + const QString baro = QString("%1_%2").arg(provider->getBarometerCelsiusTemperature(), 0, 'f', ROUNDING_DECIMALS) + .arg(provider->getBarometer_hPa(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("barometer"), baro.toLocal8Bit()); + } +} + +void MqttEventHandler::uploadAccelerometer() +{ + if (!ensureConnected(m_client)) + return; + + SensorTagDataProvider *provider = m_providerPool->currentProvider(); + + if (provider) { + const QString accel = QString("%1_%2_%3").arg(provider->getAccelometer_xAxis(), 0, 'f', ROUNDING_DECIMALS) + .arg(provider->getAccelometer_yAxis(), 0, 'f', ROUNDING_DECIMALS) + .arg(provider->getAccelometer_zAxis(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("accel"), accel.toLocal8Bit()); + } +} + +void MqttEventHandler::uploadMagnetometer() +{ + if (!ensureConnected(m_client)) + return; + + SensorTagDataProvider *provider = m_providerPool->currentProvider(); + + if (provider) { + const QString magnet = QString("%1_%2_%3").arg(provider->getMagnetometerMicroT_xAxis(), 0, 'f', ROUNDING_DECIMALS) + .arg(provider->getMagnetometerMicroT_yAxis(), 0, 'f', ROUNDING_DECIMALS) + .arg(provider->getMagnetometerMicroT_zAxis(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("magnet"), magnet.toLocal8Bit()); + } +} + +void MqttEventHandler::uploadRotation() +{ + if (!ensureConnected(m_client)) + return; + + SensorTagDataProvider *provider = m_providerPool->currentProvider(); + + if (provider) { + const QString rotation = QString("%1_%2_%3").arg(provider->getRotationX(), 0, 'f', ROUNDING_DECIMALS) + .arg(provider->getRotationY(), 0, 'f', ROUNDING_DECIMALS) + .arg(provider->getRotationZ(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("rotation"), rotation.toLocal8Bit()); + } +} + +void MqttEventHandler::clientConnected() +{ + m_pingTimer.start(); +} + +void MqttEventHandler::sendAlive() +{ + m_client->publish(QLatin1String("sensors/active"), QString::fromLocal8Bit("%1>Online").arg(m_deviceName).toLocal8Bit(), 1); +} +#endif // !MQTT_TIMER_BASED_PUBLISH + +#ifdef MQTT_TIMER_BASED_PUBLISH +void MqttUpdate::timerEvent(QTimerEvent *event) +{ + Q_UNUSED(event); + + if (!m_provider) + return; + + writeToCloud(); +} + +void MqttUpdate::writeToCloud() +{ + if (!m_provider) { + qWarning("MqttUpdate: sensor data provider not set. Data not updated"); + return; + } + + if (m_client->state() == QMqttClient::Disconnected) { + qCDebug(boot2QtDemos) << "Disconnected, need to reconnect"; + m_client->connectToHost(); + } + if (m_client->state() == QMqttClient::Connected) { + static bool sendTypeVersion = true; + if (sendTypeVersion) { + m_client->publish(m_topicPrefix + QLatin1String("type"), m_provider->sensorType()); + m_client->publish(m_topicPrefix + QLatin1String("version"), m_provider->versionString()); + sendTypeVersion = false; + } + m_client->publish(m_topicPrefix + QLatin1String("humid"), + QString("%1").arg(m_provider->getRelativeHumidity(), 0, 'f', ROUNDING_DECIMALS)); + m_client->publish(m_topicPrefix + QLatin1String("light"), + QString("%1").arg(m_provider->getLightIntensityLux(), 0, 'f', ROUNDING_DECIMALS)); + + const QString temperature = QString("%1_%2").arg(m_provider->getInfraredAmbientTemperature(), 0, 'f', ROUNDING_DECIMALS) + .arg(m_provider->getInfraredObjectTemperature(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("temperature"), temperature); + + const QString baro = QString("%1_%2").arg(m_provider->getBarometerCelsiusTemperature(), 0, 'f', ROUNDING_DECIMALS) + .arg(m_provider->getBarometer_hPa(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("barometer"), baro); + + const QString gyro = QString("%1_%2_%3").arg(m_provider->getGyroscopeX_degPerSec(), 0, 'f', ROUNDING_DECIMALS) + .arg(m_provider->getGyroscopeY_degPerSec(), 0, 'f', ROUNDING_DECIMALS) + .arg(m_provider->getGyroscopeZ_degPerSec(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("gyro"), gyro); + + const QString accel = QString("%1_%2_%3").arg(m_provider->getAccelometer_xAxis(), 0, 'f', ROUNDING_DECIMALS) + .arg(m_provider->getAccelometer_yAxis(), 0, 'f', ROUNDING_DECIMALS) + .arg(m_provider->getAccelometer_zAxis(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("accel"), accel); + + const QString magnet = QString("%1_%2_%3").arg(m_provider->getMagnetometerMicroT_xAxis(), 0, 'f', ROUNDING_DECIMALS) + .arg(m_provider->getMagnetometerMicroT_yAxis(), 0, 'f', ROUNDING_DECIMALS) + .arg(m_provider->getMagnetometerMicroT_zAxis(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("magnet"), magnet); + + const QString rotation = QString("%1_%2_%3").arg(m_provider->getRotationX(), 0, 'f', ROUNDING_DECIMALS) + .arg(m_provider->getRotationY(), 0, 'f', ROUNDING_DECIMALS) + .arg(m_provider->getRotationZ(), 0, 'f', ROUNDING_DECIMALS); + m_client->publish(m_topicPrefix + QLatin1String("rotation"), rotation); + } +} +#endif //MQTT_TIMER_BASED_PUBLISH + +MqttEventHandler::MqttEventHandler(const QString &name, QObject *parent) + : QObject(parent) +{ + m_deviceName = name; + m_topicPrefix = QString::fromLocal8Bit("sensors/%1/").arg(m_deviceName); + + m_pingTimer.setInterval(5000); + m_pingTimer.setSingleShot(false); + connect(&m_pingTimer, &QTimer::timeout, this, &MqttEventHandler::sendAlive); + + m_client = new QMqttClient; + m_client->setHostname(QLatin1String(MQTT_BROKER)); + m_client->setPort(MQTT_PORT); + m_client->setUsername(QByteArray(MQTT_USERNAME)); + m_client->setPassword(QByteArray(MQTT_PASSWORD)); + + m_client->setWillMessage(QString::fromLocal8Bit("%1>Offline").arg(m_deviceName).toLocal8Bit()); + m_client->setWillQoS(1); + m_client->setWillRetain(true); + m_client->setWillTopic(QString::fromLocal8Bit("sensors/active")); + connect(m_client, &QMqttClient::connected, this, &MqttEventHandler::clientConnected); +} + +MqttEventHandler::~MqttEventHandler() +{ + m_client->publish(QLatin1String("sensors/active"), + QString::fromLocal8Bit("%1>Offline").arg(m_deviceName).toLocal8Bit(), 1); +} diff --git a/tradeshow/iot-sensortag/mqttupdate.h b/tradeshow/iot-sensortag/mqttupdate.h new file mode 100644 index 0000000..2c2d424 --- /dev/null +++ b/tradeshow/iot-sensortag/mqttupdate.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of Qt for Device Creation. +** +** $QT_BEGIN_LICENSE:BSD$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** BSD License Usage +** Alternatively, you may use this file under the terms of the BSD license +** as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef MQTTUPDATE_H +#define MQTTUPDATE_H + +#include +#include + +class DataProviderPool; +class SensorTagDataProvider; +class QMqttClient; + +//#define MQTT_TIMER_BASED_PUBLISH 1 + +class MqttEventHandler : public QObject +{ + Q_OBJECT +public: + explicit MqttEventHandler(const QString &name, QObject *parent = 0); + ~MqttEventHandler(); + DataProviderPool *m_providerPool; +public slots: + void uploadGyro(); + void uploadTemperature(); + void uploadHumidity(); + void uploadLight(); + void uploadAltitude(); + void uploadBarometer(); + void uploadAccelerometer(); + void uploadMagnetometer(); + void uploadRotation(); + + void clientConnected(); + void sendAlive(); + +private: + QString m_deviceName; + QString m_topicPrefix; + QMqttClient *m_client; + QTimer m_pingTimer; +}; + +class MqttUpdate : public QObject +{ + Q_OBJECT +public: + explicit MqttUpdate(QObject *parent = 0); + + void setDataProviderPool(DataProviderPool *provider); + + int updateInterval() const; + void setUpdateInterval(int interval); + void restart(); + void stop(); + +#ifdef MQTT_TIMER_BASED_PUBLISH +protected: + void timerEvent(QTimerEvent* event); + virtual void writeToCloud(); +#else +#endif + +protected: + DataProviderPool *m_providerPool; +private: + QThread *m_handlerThread; + MqttEventHandler *m_handler; + int m_updateInterval; +#ifdef MQTT_TIMER_BASED_PUBLISH + int m_timerId; +#endif +}; + +#endif // MQTTUPDATE_H -- cgit v1.2.3 From a5e5b43bbedf11fea87a96d4d1635b94e08a6446 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 25 Sep 2017 14:19:49 +0200 Subject: iot-sensortag: Align font sizes 26 is used on some, but not all locations. That had the side effect, that text had different sizes on different platforms causing layouting issues. Change-Id: I057010fdf2aa562c188bd2376829d065a5eeff93 Reviewed-by: Alex Blasche --- tradeshow/iot-sensortag/resources/base/AccelChart.qml | 1 + tradeshow/iot-sensortag/resources/base/AltitudeChart.qml | 1 + tradeshow/iot-sensortag/resources/base/GyroChart.qml | 2 ++ tradeshow/iot-sensortag/resources/base/HumidityChart.qml | 2 ++ tradeshow/iot-sensortag/resources/base/MagnetometerChart.qml | 2 ++ tradeshow/iot-sensortag/resources/base/ObjectTemperatureChart.qml | 2 ++ tradeshow/iot-sensortag/resources/base/TemperatureChart.qml | 3 +++ 7 files changed, 13 insertions(+) (limited to 'tradeshow') diff --git a/tradeshow/iot-sensortag/resources/base/AccelChart.qml b/tradeshow/iot-sensortag/resources/base/AccelChart.qml index 10a7758..d037ff1 100644 --- a/tradeshow/iot-sensortag/resources/base/AccelChart.qml +++ b/tradeshow/iot-sensortag/resources/base/AccelChart.qml @@ -90,6 +90,7 @@ BaseChart { anchors.centerIn: parent text: (index == 0) ? acceXValue : ((index == 1) ? acceYValue : acceZValue) color: "white" + font.pixelSize: 26 } } diff --git a/tradeshow/iot-sensortag/resources/base/AltitudeChart.qml b/tradeshow/iot-sensortag/resources/base/AltitudeChart.qml index 2c05bc7..20a8a0e 100644 --- a/tradeshow/iot-sensortag/resources/base/AltitudeChart.qml +++ b/tradeshow/iot-sensortag/resources/base/AltitudeChart.qml @@ -152,6 +152,7 @@ BaseChart { anchors.centerIn: parent anchors.horizontalCenterOffset: 74 color: "white" + font.pixelSize: 26 } } } diff --git a/tradeshow/iot-sensortag/resources/base/GyroChart.qml b/tradeshow/iot-sensortag/resources/base/GyroChart.qml index 63a9122..f09ef6b 100644 --- a/tradeshow/iot-sensortag/resources/base/GyroChart.qml +++ b/tradeshow/iot-sensortag/resources/base/GyroChart.qml @@ -159,6 +159,7 @@ BaseChart { color: "white" anchors.left: parent.left anchors.bottom: parent.bottom + font.pixelSize: 26 } Text { @@ -170,6 +171,7 @@ BaseChart { anchors.left: coordText.right anchors.leftMargin: 16 anchors.bottom: parent.bottom + font.pixelSize: 26 } } } diff --git a/tradeshow/iot-sensortag/resources/base/HumidityChart.qml b/tradeshow/iot-sensortag/resources/base/HumidityChart.qml index 582128f..869288a 100644 --- a/tradeshow/iot-sensortag/resources/base/HumidityChart.qml +++ b/tradeshow/iot-sensortag/resources/base/HumidityChart.qml @@ -102,6 +102,7 @@ BaseChart { text: "Max\n" + maxHumi.toFixed(0) + " %" lineHeight: 0.8 color: "white" + font.pixelSize: 26 } Text { @@ -111,6 +112,7 @@ BaseChart { text: "Min\n" + minHumi.toFixed(0) + " %" lineHeight: 0.8 color: "white" + font.pixelSize: 26 } } } diff --git a/tradeshow/iot-sensortag/resources/base/MagnetometerChart.qml b/tradeshow/iot-sensortag/resources/base/MagnetometerChart.qml index 6f0d3c7..2b2ccac 100644 --- a/tradeshow/iot-sensortag/resources/base/MagnetometerChart.qml +++ b/tradeshow/iot-sensortag/resources/base/MagnetometerChart.qml @@ -153,6 +153,7 @@ BaseChart { color: (index == 0) ? xColor : ((index == 1) ? yColor : zColor) anchors.left: parent.left anchors.bottom: parent.bottom + font.pixelSize: 26 } Text { @@ -164,6 +165,7 @@ BaseChart { anchors.left: coordText.right anchors.leftMargin: 16 anchors.bottom: parent.bottom + font.pixelSize: 26 } } } diff --git a/tradeshow/iot-sensortag/resources/base/ObjectTemperatureChart.qml b/tradeshow/iot-sensortag/resources/base/ObjectTemperatureChart.qml index ffba32b..a594257 100644 --- a/tradeshow/iot-sensortag/resources/base/ObjectTemperatureChart.qml +++ b/tradeshow/iot-sensortag/resources/base/ObjectTemperatureChart.qml @@ -89,6 +89,7 @@ BaseChart { anchors.centerIn: gauge anchors.horizontalCenterOffset: -120 anchors.verticalCenterOffset: 60 + font.pixelSize: 26 } Text { @@ -107,6 +108,7 @@ BaseChart { anchors.centerIn: gauge anchors.horizontalCenterOffset: 120 anchors.verticalCenterOffset: -30 + font.pixelSize: 26 } } } diff --git a/tradeshow/iot-sensortag/resources/base/TemperatureChart.qml b/tradeshow/iot-sensortag/resources/base/TemperatureChart.qml index dbad24b..7a90dea 100644 --- a/tradeshow/iot-sensortag/resources/base/TemperatureChart.qml +++ b/tradeshow/iot-sensortag/resources/base/TemperatureChart.qml @@ -106,6 +106,7 @@ BaseChart { anchors.horizontalCenter: reading.horizontalCenter anchors.top: parent.top color: "white" + font.pixelSize: 26 } Image { @@ -132,6 +133,7 @@ BaseChart { color: "white" anchors.bottom: parent.bottom anchors.horizontalCenter: reading.horizontalCenter + font.pixelSize: 26 } Text { @@ -143,6 +145,7 @@ BaseChart { color: "white" anchors.right: parent.right anchors.verticalCenter: reading.verticalCenter + font.pixelSize: 26 } } -- cgit v1.2.3 From 231b31ebec86078df293fbf9e265c5223d9e703b Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 25 Sep 2017 14:20:09 +0200 Subject: iot-sensortag: Show fullscreen on Android Change-Id: I14a2e55adea3072c23cd25b27d5f65c08a176857 Reviewed-by: Alex Blasche --- tradeshow/iot-sensortag/main.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'tradeshow') diff --git a/tradeshow/iot-sensortag/main.cpp b/tradeshow/iot-sensortag/main.cpp index 555d1a8..5dd9a7e 100644 --- a/tradeshow/iot-sensortag/main.cpp +++ b/tradeshow/iot-sensortag/main.cpp @@ -129,10 +129,15 @@ int main(int argc, char *argv[]) QString mainFile; QUrl styleFile; - QString uiVariant; - bool fullScreen; - int appWidth = 0; - int appHeight = 0; + QString uiVariant = QStringLiteral("small"); + bool fullScreen = +#ifdef Q_OS_ANDROID + true; +#else + false; +#endif + int appWidth = 1920; + int appHeight = 1080; QScreen* scr = qApp->screens().at(0); @@ -151,11 +156,6 @@ int main(int argc, char *argv[]) mainFile = namingScheme + QStringLiteral("/resources/small/MainSmall.qml"); styleFile = namingScheme + QStringLiteral("/resources/small/StyleSmall.qml"); - uiVariant = "small"; - fullScreen = false; - appWidth = 1920; - appHeight = 1080; - qmlRegisterSingletonType(styleFile, "Style", 1,0, "Style"); if (qEnvironmentVariableIsSet("QT_IOS_DEMO_NO_FULLSCREEN")) { -- cgit v1.2.3 From 79e7853ed4b86d9d3077de7d1304a5becb227847 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 25 Sep 2017 16:02:29 +0200 Subject: iot-sensortag: Disable dateview in portrait mode Change-Id: Ic57220e63398f2e7a8745aaa4bcbd341a2b02010 Reviewed-by: Alex Blasche --- tradeshow/iot-sensortag/resources/base/TopToolbar.qml | 1 + 1 file changed, 1 insertion(+) (limited to 'tradeshow') diff --git a/tradeshow/iot-sensortag/resources/base/TopToolbar.qml b/tradeshow/iot-sensortag/resources/base/TopToolbar.qml index 0d15ce1..6e5d9d2 100644 --- a/tradeshow/iot-sensortag/resources/base/TopToolbar.qml +++ b/tradeshow/iot-sensortag/resources/base/TopToolbar.qml @@ -120,6 +120,7 @@ Item { horizontalAlignment: Text.AlignRight font.pixelSize: Style.topToolbarSmallFontSize font.capitalization: Font.AllUppercase + visible: rotationMain.visible MouseArea { anchors.fill: parent onClicked: parent.showAddress = !parent.showAddress -- cgit v1.2.3 From d53a691180070e8126c24fae2115cb7afd867a94 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 28 Sep 2017 11:16:18 +0200 Subject: iot-sensortag: Do not enable MQTT by default This was agreed in a previous patch set for bb226a8dc9b6508c8d72c67b5260b9a733f7fca1. However, it slipped in due to wrong rebasing. Change-Id: I2725ae54da6573a9bc2dc5f965b8e9c0c65997a0 Reviewed-by: Oliver Wolff --- tradeshow/iot-sensortag/SensorTagDemo.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tradeshow') diff --git a/tradeshow/iot-sensortag/SensorTagDemo.pro b/tradeshow/iot-sensortag/SensorTagDemo.pro index c69a181..bae8f07 100644 --- a/tradeshow/iot-sensortag/SensorTagDemo.pro +++ b/tradeshow/iot-sensortag/SensorTagDemo.pro @@ -25,7 +25,7 @@ win32|linux|android:!qnx { # For using MQTT upload enable this config. # This enables both, host and client mode -CONFIG += UPDATE_TO_MQTT_BROKER +# CONFIG += UPDATE_TO_MQTT_BROKER win32:!contains(CONFIG, UPDATE_TO_MQTT_BROKER) { WASTORAGE_PATH = $$(WASTORAGE_LOCATION) -- cgit v1.2.3 From ba42ff33c9d84bf8da482e673f61e9d1de33e1a3 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 27 Sep 2017 13:06:15 +0200 Subject: iot-sensortag: Add logging window This is most useful in the embedded use-case. Usually there is no debug connection and initialization of a bluetooth connection can take very long. Change-Id: If5b6e8a6e684d2340d6a52b8b21bec25630d6874 Reviewed-by: Oliver Wolff --- tradeshow/iot-sensortag/main.cpp | 17 +++++++++++++++ .../iot-sensortag/resources/base/TopToolbar.qml | 24 ++++++++++++++++++++++ tradeshow/iot-sensortag/resources/base/main.qml | 1 + 3 files changed, 42 insertions(+) (limited to 'tradeshow') diff --git a/tradeshow/iot-sensortag/main.cpp b/tradeshow/iot-sensortag/main.cpp index 5dd9a7e..ba5324b 100644 --- a/tradeshow/iot-sensortag/main.cpp +++ b/tradeshow/iot-sensortag/main.cpp @@ -78,8 +78,22 @@ Q_DECLARE_LOGGING_CATEGORY(boot2QtDemos) Q_LOGGING_CATEGORY(boot2QtDemos, "boot2qt.demos.iot") +QString loggingOutput; +QQuickWindow *loggingItem{nullptr}; +void handleMessageOutput(QtMsgType, const QMessageLogContext &, const QString &text) +{ + loggingOutput.prepend("\n"); + loggingOutput.prepend(text); + + loggingOutput.chop(loggingOutput.size() - 1024); + if (loggingItem) + loggingItem->setProperty("loggingOutput", loggingOutput); +} + int main(int argc, char *argv[]) { + auto oldHandler = qInstallMessageHandler(handleMessageOutput); + // QtChars mandate using QApplication as it uses the graphics view fw QApplication app(argc, argv); @@ -184,9 +198,12 @@ int main(int argc, char *argv[]) item->setProperty("contentFile", mainFile); item->setProperty("seriesStorage", QVariant::fromValue(&seriesStorage)); item->setProperty("addresses", addressString); + loggingItem = item; } int returnValue = app.exec(); remoteProviderPool->stopScanning(); + qInstallMessageHandler(oldHandler); + return returnValue; } diff --git a/tradeshow/iot-sensortag/resources/base/TopToolbar.qml b/tradeshow/iot-sensortag/resources/base/TopToolbar.qml index 6e5d9d2..69722b7 100644 --- a/tradeshow/iot-sensortag/resources/base/TopToolbar.qml +++ b/tradeshow/iot-sensortag/resources/base/TopToolbar.qml @@ -67,6 +67,26 @@ Item { visible: true } + Image { + id: logWindow + source: "images/bg_blue.jpg" + x: sensorItem.x + y: topToolbar.height + width: Math.min(mainWindow.width, 600) + height: Math.min(mainWindow.height - topToolbar.height, 400) + anchors.horizontalCenter: parent.horizontalCenter + visible: false + Text { + clip: true + color: "white" + font.pixelSize: 26 + text: mainWindow.loggingOutput ? mainWindow.loggingOutput : "...debug..." + anchors.fill: parent + anchors.margins: 15 + } + } + + Item { id: sensorItem height: topToolbar.height @@ -134,6 +154,10 @@ Item { font.pixelSize: Style.topToolbarLargeFontSize anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.bottom + MouseArea { + anchors.fill: parent + onClicked: clickBait.activate(logWindow) + } } Timer { diff --git a/tradeshow/iot-sensortag/resources/base/main.qml b/tradeshow/iot-sensortag/resources/base/main.qml index caa8617..c756c6d 100644 --- a/tradeshow/iot-sensortag/resources/base/main.qml +++ b/tradeshow/iot-sensortag/resources/base/main.qml @@ -63,6 +63,7 @@ Window { property real globalBlinkOpacity: 1.0 property string addresses : "" property bool localSelected : true + property var loggingOutput : null function getCurrentPool() { if (localSelected) -- cgit v1.2.3 From 21350aac26961e48e2610f157725a2a8873b285b Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Mon, 2 Oct 2017 12:54:24 +0200 Subject: iot-sensortag: Use double-click to select connection Change-Id: I46c3860799018e51f74df8d24dd54eccab02db7a Reviewed-by: Oliver Wolff --- .../resources/base/SensorSettings.qml | 52 ++++++++++++---------- 1 file changed, 29 insertions(+), 23 deletions(-) (limited to 'tradeshow') diff --git a/tradeshow/iot-sensortag/resources/base/SensorSettings.qml b/tradeshow/iot-sensortag/resources/base/SensorSettings.qml index 7661325..5302816 100644 --- a/tradeshow/iot-sensortag/resources/base/SensorSettings.qml +++ b/tradeshow/iot-sensortag/resources/base/SensorSettings.qml @@ -63,6 +63,30 @@ Rectangle { height: 800 anchors.horizontalCenter: parent.horizontalCenter + function createSensorConnection() { + clickBait.deactivate() + + var currentPool = getCurrentPool(); + if (currentPool.dataProviders[sensorListView.currentIndex] === singleSensorSource) { + console.log("Same data provider selected, nothing to change...") + return; + } + + if (singleSensorSource) + singleSensorSource.endDataFetching(); + // UI gets information about the intended setup of the + // sensor even though they have not been really discovered yet + if (currentPool) { + singleSensorSource = currentPool.dataProviders[sensorListView.currentIndex] + currentPool.currentProviderIndex = sensorListView.currentIndex + + seriesStorage.setDataProviderPool(currentPool); + seriesStorage.dataProviderPoolChanged(); + + singleSensorSource.startDataFetching() + } + } + Image { source: "images/bg_blue.jpg" anchors.fill: parent @@ -151,6 +175,10 @@ Rectangle { MouseArea { anchors.fill: parent onClicked: sensorListView.currentIndex = index + onDoubleClicked: { + sensorListView.currentIndex = index + createSensorConnection() + } } } } @@ -173,29 +201,7 @@ Rectangle { id: connectButtonArea anchors.fill: parent enabled: sensorListView.currentIndex != -1 - onClicked: { - clickBait.deactivate() - - var currentPool = getCurrentPool(); - if (currentPool.dataProviders[sensorListView.currentIndex] === singleSensorSource) { - console.log("Same data provider selected, nothing to change...") - return; - } - - if (singleSensorSource) - singleSensorSource.endDataFetching(); - // UI gets information about the intended setup of the - // sensor even though they have not been really discovered yet - if (currentPool) { - singleSensorSource = currentPool.dataProviders[sensorListView.currentIndex] - currentPool.currentProviderIndex = sensorListView.currentIndex - - seriesStorage.setDataProviderPool(currentPool); - seriesStorage.dataProviderPoolChanged(); - - singleSensorSource.startDataFetching() - } - } + onClicked: createSensorConnection() } } -- cgit v1.2.3 From 3302a40a4e4a83d53493a832bc9b8486b3ad549a Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 4 Oct 2017 12:32:42 +0200 Subject: iot-sensortag: Add Uuid fallback for device id All Android test devices report localhost as hostname. That causes the remote display to not show any other android device, but also have multiple localhost devices report data. Change-Id: I144800d876faf35bc9ff8e526be31d9c322032dc Reviewed-by: Oliver Wolff --- tradeshow/iot-sensortag/mqttupdate.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'tradeshow') diff --git a/tradeshow/iot-sensortag/mqttupdate.cpp b/tradeshow/iot-sensortag/mqttupdate.cpp index f574965..45ea238 100644 --- a/tradeshow/iot-sensortag/mqttupdate.cpp +++ b/tradeshow/iot-sensortag/mqttupdate.cpp @@ -55,6 +55,7 @@ #include "demodataproviderpool.h" #include "mqttdataproviderpool.h" +#include #include #include @@ -85,7 +86,11 @@ void MqttUpdate::setDataProviderPool(DataProviderPool *provider) if (!provider) return; - const QString hostname = QSysInfo::machineHostName(); + QString hostname = QSysInfo::machineHostName(); + if (hostname == QLatin1String("localhost")) { + hostname = QUuid::createUuid().toString(); + qCDebug(boot2QtDemos) << "localhost not unique. New ID:" << hostname; + } m_handler = new MqttEventHandler(hostname + QLatin1String(" - ") + provider->id()); m_handler->m_providerPool = m_providerPool; -- cgit v1.2.3