diff options
author | Mikko Gronoff <mikko.gronoff@qt.io> | 2017-10-11 13:26:57 +0300 |
---|---|---|
committer | Mikko Gronoff <mikko.gronoff@qt.io> | 2017-10-11 13:32:21 +0300 |
commit | 444878981185912f88155f27635b509b613a48e8 (patch) | |
tree | 33506a21e7bc9189ea3b7ed1d83aef8916d7cd8e | |
parent | 7f17ecb20a42dbf6ad2d994f9521e738b4b97a11 (diff) | |
parent | 3302a40a4e4a83d53493a832bc9b8486b3ad549a (diff) |
Merge remote-tracking branch 'origin/5.10' into dev
* origin/5.10:
iot-sensortag: Add Uuid fallback for device id
iot-sensortag: Use double-click to select connection
iot-sensortag: Add logging window
iot-sensortag: Do not enable MQTT by default
Merge remote-tracking branch 'origin/5.9' into 5.10
iot-sensortag: Disable dateview in portrait mode
iot-sensortag: Show fullscreen on Android
iot-sensortag: Align font sizes
iot-sensortag: Add support for MQTT
iot-sensortag: Redesign of example
Fix typo
Doc: Bump version to 5.10.0
Doc: Bump version to 5.9.2
Change-Id: Id006d6911a42db2a493f7b3f0eb891c791a5879c
73 files changed, 1534 insertions, 1111 deletions
diff --git a/basicsuite/graphicaleffects/main.qml b/basicsuite/graphicaleffects/main.qml index 29bf3cc..1b31a9d 100644 --- a/basicsuite/graphicaleffects/main.qml +++ b/basicsuite/graphicaleffects/main.qml @@ -78,7 +78,7 @@ Item { ListModel { id: listModel - ListElement { name: "Brignthness / Contrast"; file: "effect_BrightnessContrast.qml" } + ListElement { name: "Brightness / Contrast"; file: "effect_BrightnessContrast.qml" } ListElement { name: "Colorize"; file: "effect_Colorize.qml" } ListElement { name: "Displacement"; file: "effect_Displacement.qml" } ListElement { name: "Drop Shadow"; file: "effect_DropShadow.qml" } diff --git a/doc/b2qt-demos.qdoc b/doc/b2qt-demos.qdoc index af970c7..b9fd565 100644 --- a/doc/b2qt-demos.qdoc +++ b/doc/b2qt-demos.qdoc @@ -50,7 +50,7 @@ /*! \page index.html - \title Qt 5.9 for Device Creation Examples and Demos + \title Qt 5.10.0 for Device Creation Examples and Demos \SDK has a number of examples and demos. These are included in the \B2Q images, available in the launcher that is run by default at diff --git a/doc/b2qt-demos.qdocconf b/doc/b2qt-demos.qdocconf index 5e30459..2f4b125 100644 --- a/doc/b2qt-demos.qdocconf +++ b/doc/b2qt-demos.qdocconf @@ -5,8 +5,8 @@ outputencoding = UTF-8 sourceencoding = UTF-8 project = QtforDeviceCreationDemos -description = Qt 5.9 for Device Creation Examples and Demos -version = 5.9.0 +description = Qt 5.10.0 for Device Creation Examples and Demos +version = 5.10.0 sourcedirs = . imagedirs += images @@ -21,9 +21,9 @@ exampledirs = .. qhp.projects = QtforDeviceCreationDemos qhp.QtforDeviceCreationDemos.file = b2qt-demos.qhp -qhp.QtforDeviceCreationDemos.namespace = com.digia.b2qt-demos.590 +qhp.QtforDeviceCreationDemos.namespace = org.qt-project.b2qt-demos.5100 qhp.QtforDeviceCreationDemos.virtualFolder = b2qt-demos -qhp.QtforDeviceCreationDemos.indexTitle = Qt 5.9 for Device Creation Examples and Demos +qhp.QtforDeviceCreationDemos.indexTitle = Qt 5.10.0 for Device Creation Examples and Demos qhp.QtforDeviceCreationDemos.indexRoot = qhp.QtforDeviceCreationDemos.subprojects = demos @@ -35,4 +35,4 @@ manifestmeta.b2qt.names = "QtforDeviceCreationDemos/*" macro.B2Q = "Boot to Qt" macro.SDK = "Qt for Device Creation" -navigation.landingpage = "Qt 5.9 for Device Creation Examples and Demos" +navigation.landingpage = "Qt 5.10.0 for Device Creation Examples and Demos" diff --git a/tradeshow/iot-sensortag/SensorTagDemo.pro b/tradeshow/iot-sensortag/SensorTagDemo.pro index bd79351..bae8f07 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/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)<<Q_FUNC_INFO; + qCDebug(boot2QtDemos) << Q_FUNC_INFO << m_btDevice; if (m_btDevice) { setState(Scanning); m_btDevice->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 <QQmlEngine> #include <QJSEngine> #include <QTimer> +#include <QBluetoothDeviceInfo> 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<QLowEnergyController::Error>::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<void(QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&QLowEnergyService::error), + connect(m_irTemperatureService, QOverload<QLowEnergyService::ServiceError>::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<void(QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&QLowEnergyService::error), + connect(m_baroService, QOverload<QLowEnergyService::ServiceError>::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<void(QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&QLowEnergyService::error), + connect(m_humidityService, QOverload<QLowEnergyService::ServiceError>::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<void(QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&QLowEnergyService::error), + connect(m_lightService, QOverload<QLowEnergyService::ServiceError>::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<void(QLowEnergyService::*)(QLowEnergyService::ServiceError)>(&QLowEnergyService::error), + connect(m_motionService, QOverload<QLowEnergyService::ServiceError>::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<QSslError> &errors) +void CloudDataProvider::sslErrors(QNetworkReply *, const QList<QSslError> &errors) { QString errorString; for (const QSslError &error : errors) { @@ -246,7 +246,7 @@ void CloudDataProvider::sslErrors(QNetworkReply*, const QList<QSslError> &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<const wchar_t*>(QString(accStr).utf16())); + const utility::string_t storage_connection_string(reinterpret_cast<const wchar_t *>(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<const wchar_t*>(sensorData.utf16())); + blob.upload_text(reinterpret_cast<const wchar_t *>(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<SensorTagDataProvider> dataProviders READ dataProviders NOTIFY dataProvidersChanged) + Q_PROPERTY(QQmlListProperty<SensorTagDataProvider> 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<SensorTagDataProvider> 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<SensorTagDataProvider*> m_dataProviders; + QList<SensorTagDataProvider *> 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<DemoCloudProvider*>(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<BluetoothDataProvider*>(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<SensorTagDataProvider*>& dataProviders); + void setDataProviders(const QList<SensorTagDataProvider *> &dataProviders); QString sensorType() const override; QString versionString() const override; @@ -108,7 +107,7 @@ public: float getRotationZ() const override; float getAltitude() const override; - QList<SensorTagDataProvider*> m_dataProviders; + QList<SensorTagDataProvider *> m_dataProviders; }; #endif // DEMODATAPROVIDERPOOL_H diff --git a/tradeshow/iot-sensortag/main.cpp b/tradeshow/iot-sensortag/main.cpp index 5164919..ba5324b 100644 --- a/tradeshow/iot-sensortag/main.cpp +++ b/tradeshow/iot-sensortag/main.cpp @@ -47,13 +47,6 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#include <QApplication> -#include <QQmlApplicationEngine> -#include <QQuickWindow> -#include <QQmlContext> -#include <QCommandLineParser> -#include <QFontDatabase> -#include <QScreen> #if defined(RUNS_AS_HOST) #include "bluetoothdataprovider.h" @@ -67,77 +60,77 @@ #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 <QApplication> +#include <QQmlApplicationEngine> +#include <QQuickWindow> +#include <QQmlContext> +#include <QCommandLineParser> +#include <QFontDatabase> +#include <QScreen> + 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); 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"; +#if defined(MQTT_UPLOAD) + remoteProviderPool = new MqttDataProviderPool; #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<SensorTagDataProviderPool*>(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<SensorTagDataProvider>("SensorTag.DataProvider", 1, 0, "SensorTagData"); - qmlRegisterType<SensorTagDataProvider>("SensorTag.DataProvider", 1, 0, "ProviderState"); qmlRegisterType<DataProviderPool>("SensorTag.DataProvider", 1, 0, "DataProviderPool"); qmlRegisterType<SeriesStorage>("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; - if (sensorSource == "sensor" || sensorSource == "mock") { - update.setDataProviderPool(dataProviderPool); - update.restart(); - } +# else + MqttUpdate update; +# endif + + update.setDataProviderPool(localProviderPool); + update.restart(); #endif #ifdef DEPLOY_TO_FS @@ -150,10 +143,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); @@ -169,34 +167,8 @@ 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"); qmlRegisterSingletonType(styleFile, "Style", 1,0, "Style"); @@ -221,12 +193,17 @@ 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); + loggingItem = item; } int returnValue = app.exec(); - dataProviderPool->stopScanning(); + remoteProviderPool->stopScanning(); + + qInstallMessageHandler(oldHandler); + 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 <QtCore/QDateTime> #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 <QtQml/QQmlEngine> #include <QtQml/QJSEngine> #include <QtCore/QTimer> @@ -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 aceb172..6592e1b 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 | SensorTagDataProvider::Altitude); 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.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 <QUrl> +#include <QLoggingCategory> +#include <QTimer> + +#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/resources/medium/StyleMedium.qml b/tradeshow/iot-sensortag/mqttdataprovider.h index e4d439d..9a52332 100644 --- a/tradeshow/iot-sensortag/resources/medium/StyleMedium.qml +++ b/tradeshow/iot-sensortag/mqttdataprovider.h @@ -47,13 +47,37 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -pragma Singleton -import QtQuick 2.0 +#ifndef MQTTDATAPROVIDER_H +#define MQTTDATAPROVIDER_H -QtObject { - property int indicatorTitleFontSize: 22 - property int indicatorTitleSize: 41 +#include "sensortagdataprovider.h" +#include <QtQml/QQmlEngine> +#include <QtQml/QJSEngine> +#include <QtMqtt/QMqttClient> +#include <QtMqtt/QMqttSubscription> - property int topToolbarSmallFontSize: 20 - property int topToolbarLargeFontSize: 62 -} +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.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 <QtCore/QDebug> + +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<QString> 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/resources/large/StyleLarge.qml b/tradeshow/iot-sensortag/mqttdataproviderpool.h index e4d439d..1ba33ff 100644 --- a/tradeshow/iot-sensortag/resources/large/StyleLarge.qml +++ b/tradeshow/iot-sensortag/mqttdataproviderpool.h @@ -47,13 +47,31 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -pragma Singleton -import QtQuick 2.0 +#ifndef MQTTDATAPROVIDERPOOL_H +#define MQTTDATAPROVIDERPOOL_H -QtObject { - property int indicatorTitleFontSize: 22 - property int indicatorTitleSize: 41 +#include "dataproviderpool.h" +#include <QtMqtt/QMqttClient> - property int topToolbarSmallFontSize: 20 - property int topToolbarLargeFontSize: 62 -} +class MqttDataProvider; + +#define MQTT_BROKER "" +#define MQTT_PORT 1883 +#define MQTT_USERNAME "" +#define MQTT_PASSWORD "" + +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/mqttupdate.cpp b/tradeshow/iot-sensortag/mqttupdate.cpp new file mode 100644 index 0000000..45ea238 --- /dev/null +++ b/tradeshow/iot-sensortag/mqttupdate.cpp @@ -0,0 +1,376 @@ +/**************************************************************************** +** +** 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 <QtCore/QUuid> +#include <QtMqtt/QtMqtt> +#include <QSysInfo> + +#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; + + 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; + + 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 <QObject> +#include <QTimer> + +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 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/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..f09ef6b 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 @@ -160,6 +159,7 @@ BaseChart { color: "white" anchors.left: parent.left anchors.bottom: parent.bottom + font.pixelSize: 26 } Text { @@ -171,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 60d1ee7..869288a 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 @@ -104,6 +102,7 @@ BaseChart { text: "Max\n" + maxHumi.toFixed(0) + " %" lineHeight: 0.8 color: "white" + font.pixelSize: 26 } Text { @@ -113,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 cf4a409..2b2ccac 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" @@ -154,6 +153,7 @@ BaseChart { color: (index == 0) ? xColor : ((index == 1) ? yColor : zColor) anchors.left: parent.left anchors.bottom: parent.bottom + font.pixelSize: 26 } Text { @@ -165,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/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..5302816 100644 --- a/tradeshow/iot-sensortag/resources/base/SensorSettings.qml +++ b/tradeshow/iot-sensortag/resources/base/SensorSettings.qml @@ -53,152 +53,162 @@ 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" + + color: "transparent" + width: 800 + 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; + } - property alias listModelCount: list.count + 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 - width: 620 - height: 480 - color: "black" + seriesStorage.setDataProviderPool(currentPool); + seriesStorage.dataProviderPoolChanged(); - Text { - id: titleText - color: "white" - text: "SENSOR SETTINGS" - font.pixelSize: Style.indicatorTitleFontSize - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - anchors.topMargin: 8 + singleSensorSource.startDataFetching() + } } Image { - id: icon - - anchors.top: titleText.bottom - anchors.horizontalCenter: parent.horizontalCenter - anchors.margins: 8 - source: pathPrefix + "Toolbar/icon_topbar_sensor.png" + source: "images/bg_blue.jpg" + anchors.fill: parent } - 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 - 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; + Image { + id: separator + source: pathPrefix + "General/separator.png" + anchors.top: parent.top + width: parent.width + transform: Rotation { + origin.x: separator.width / 2 + origin.y: separator.height / 2 + angle: 180 } + } - 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(); - } - } - } + 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 + } + } - 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 { + 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 + } + } - Item { - height: 30 - width: 10 - } + MouseArea { + anchors.fill: parent + onClicked: localSelected = !localSelected + } + } - Text { - color: "white" - text: "Provides data for:" - font.pixelSize: 14 - } + ListView { + 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 - Text { - color: "white" - lineHeight: 0.7 - text: list.getTagTypeStr(modelData.tagType()) - font.pixelSize: 14 + 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 + onDoubleClicked: { + sensorListView.currentIndex = index + createSensorConnection() } } } } + + 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: createSensorConnection() + } + } + + Image { + id: bottomSeparator + source: pathPrefix + "General/separator.png" + anchors.bottom: parent.bottom + width: parent.width + } } 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 } } diff --git a/tradeshow/iot-sensortag/resources/base/TopToolbar.qml b/tradeshow/iot-sensortag/resources/base/TopToolbar.qml index fd5054d..69722b7 100644 --- a/tradeshow/iot-sensortag/resources/base/TopToolbar.qml +++ b/tradeshow/iot-sensortag/resources/base/TopToolbar.qml @@ -57,63 +57,42 @@ 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 + width: Math.min(mainWindow.width, 800) + height: mainWindow.height - topToolbar.height + visible: true } - 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" - } - + 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 { - id: cloudText + clip: true color: "white" - text: "CLOUD" - width: contentWidth - font.pixelSize: Style.topToolbarSmallFontSize - anchors.verticalCenter: icon.verticalCenter - anchors.left: icon.right - anchors.margins: 8 - } - - MouseArea { + font.pixelSize: 26 + text: mainWindow.loggingOutput ? mainWindow.loggingOutput : "...debug..." anchors.fill: parent - onClicked: clickBait.activate(cloudSettings) + anchors.margins: 15 } } + 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 +106,7 @@ Item { Text { anchors.centerIn: parent - text: sensorList.listModelCount + text: sensorList.sensorCount color: "white" font.pixelSize: Style.topToolbarSmallFontSize } @@ -161,6 +140,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 @@ -174,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 { @@ -233,4 +217,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..c756c6d 100644 --- a/tradeshow/iot-sensortag/resources/base/main.qml +++ b/tradeshow/iot-sensortag/resources/base/main.qml @@ -55,11 +55,22 @@ 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 + property var loggingOutput : null + + function getCurrentPool() { + if (localSelected) + return localProviderPool + else + return remoteProviderPool + } // Size defaults to the small display width: 1920 @@ -74,13 +85,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/images/AirPressure/AirPre_base_gauge.png b/tradeshow/iot-sensortag/resources/large/images/AirPressure/AirPre_base_gauge.png Binary files differdeleted file mode 100644 index 30a24b8..0000000 --- a/tradeshow/iot-sensortag/resources/large/images/AirPressure/AirPre_base_gauge.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 5a4bcf0..0000000 --- a/tradeshow/iot-sensortag/resources/large/images/AmbientTemperature/ambTemp_display_amb.png +++ /dev/null diff --git a/tradeshow/iot-sensortag/resources/large/images/General/icon_sensor.png b/tradeshow/iot-sensortag/resources/large/images/General/icon_sensor.png Binary files differdeleted file mode 100644 index 8157ef7..0000000 --- a/tradeshow/iot-sensortag/resources/large/images/General/icon_sensor.png +++ /dev/null diff --git a/tradeshow/iot-sensortag/resources/large/images/General/separator.png b/tradeshow/iot-sensortag/resources/large/images/General/separator.png Binary files differdeleted file mode 100644 index 4dae4f8..0000000 --- a/tradeshow/iot-sensortag/resources/large/images/General/separator.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 0d0331c..0000000 --- a/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_base_gauge.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 381c4dd..0000000 --- a/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_max_hum.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index c3f9442..0000000 --- a/tradeshow/iot-sensortag/resources/large/images/Humidity/humidity_min_hum.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 6a68729..0000000 --- a/tradeshow/iot-sensortag/resources/large/images/Light/light_base_gauge.png +++ /dev/null diff --git a/tradeshow/iot-sensortag/resources/large/images/Light/light_brightness.png b/tradeshow/iot-sensortag/resources/large/images/Light/light_brightness.png Binary files differdeleted file mode 100644 index 45b1e2b..0000000 --- a/tradeshow/iot-sensortag/resources/large/images/Light/light_brightness.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index a506d2a..0000000 --- a/tradeshow/iot-sensortag/resources/large/images/ObjectTemperature/objTemp_base_circle.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index bc320ac..0000000 --- a/tradeshow/iot-sensortag/resources/large/images/ObjectTemperature/objTemp_display_obj.png +++ /dev/null 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/images/AirPressure/AirPre_base_gauge.png b/tradeshow/iot-sensortag/resources/medium/images/AirPressure/AirPre_base_gauge.png Binary files differdeleted file mode 100644 index 2f1d658..0000000 --- a/tradeshow/iot-sensortag/resources/medium/images/AirPressure/AirPre_base_gauge.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index cad440a..0000000 --- a/tradeshow/iot-sensortag/resources/medium/images/AmbientTemperature/ambTemp_display_amb.png +++ /dev/null diff --git a/tradeshow/iot-sensortag/resources/medium/images/General/icon_sensor.png b/tradeshow/iot-sensortag/resources/medium/images/General/icon_sensor.png Binary files differdeleted file mode 100644 index 49cc090..0000000 --- a/tradeshow/iot-sensortag/resources/medium/images/General/icon_sensor.png +++ /dev/null diff --git a/tradeshow/iot-sensortag/resources/medium/images/General/separator.png b/tradeshow/iot-sensortag/resources/medium/images/General/separator.png Binary files differdeleted file mode 100644 index dbd25a4..0000000 --- a/tradeshow/iot-sensortag/resources/medium/images/General/separator.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 494a0e6..0000000 --- a/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_base_gauge.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index c4a7d7b..0000000 --- a/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_max_hum.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 75b83d1..0000000 --- a/tradeshow/iot-sensortag/resources/medium/images/Humidity/humidity_min_hum.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 9c66fbb..0000000 --- a/tradeshow/iot-sensortag/resources/medium/images/Light/light_base_gauge.png +++ /dev/null diff --git a/tradeshow/iot-sensortag/resources/medium/images/Light/light_brightness.png b/tradeshow/iot-sensortag/resources/medium/images/Light/light_brightness.png Binary files differdeleted file mode 100644 index fc8e82a..0000000 --- a/tradeshow/iot-sensortag/resources/medium/images/Light/light_brightness.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 86c966f..0000000 --- a/tradeshow/iot-sensortag/resources/medium/images/ObjectTemperature/objTemp_base_circle.png +++ /dev/null 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 Binary files differdeleted file mode 100644 index 77d53f3..0000000 --- a/tradeshow/iot-sensortag/resources/medium/images/ObjectTemperature/objTemp_display_obj.png +++ /dev/null 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 <QtCore/QtMath> @@ -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 <QObject> #include <QString> #include <QColor> @@ -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<QBluetoothDeviceDiscoveryAgent::Error>::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<BluetoothDataProvider*>(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<BluetoothDataProvider *>(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<SensorTagDataProvider*>(sender()); + SensorTagDataProvider *provider = static_cast<SensorTagDataProvider *>(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<QBluetoothDeviceInfo> 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 @@ -<RCC> - <qresource prefix="/"> - <file>resources/large/MainLarge.qml</file> - <file>resources/large/StyleLarge.qml</file> - <file>resources/large/images/General/icon_sensor.png</file> - <file>resources/large/images/General/separator.png</file> - <file>resources/large/images/AmbientTemperature/ambTemp_display_amb.png</file> - <file>resources/large/images/Humidity/humidity_base_gauge.png</file> - <file>resources/large/images/Humidity/humidity_max_hum.png</file> - <file>resources/large/images/Humidity/humidity_min_hum.png</file> - <file>resources/large/images/ObjectTemperature/objTemp_base_circle.png</file> - <file>resources/large/images/ObjectTemperature/objTemp_display_obj.png</file> - <file>resources/large/images/Light/light_base_gauge.png</file> - <file>resources/large/images/Light/light_brightness.png</file> - <file>resources/large/images/AirPressure/AirPre_base_gauge.png</file> - </qresource> -</RCC> 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 @@ -<RCC> - <qresource prefix="/"> - <file>resources/medium/MainMedium.qml</file> - <file>resources/medium/StyleMedium.qml</file> - <file>resources/medium/images/AmbientTemperature/ambTemp_display_amb.png</file> - <file>resources/medium/images/General/icon_sensor.png</file> - <file>resources/medium/images/General/separator.png</file> - <file>resources/medium/images/Humidity/humidity_max_hum.png</file> - <file>resources/medium/images/Humidity/humidity_min_hum.png</file> - <file>resources/medium/images/Humidity/humidity_base_gauge.png</file> - <file>resources/medium/images/ObjectTemperature/objTemp_base_circle.png</file> - <file>resources/medium/images/ObjectTemperature/objTemp_display_obj.png</file> - <file>resources/medium/images/Light/light_base_gauge.png</file> - <file>resources/medium/images/Light/light_brightness.png</file> - <file>resources/medium/images/AirPressure/AirPre_base_gauge.png</file> - </qresource> -</RCC> |