summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorAlex Blasche <alexander.blasche@qt.io>2017-02-28 15:30:46 +0100
committerOliver Wolff <oliver.wolff@qt.io>2017-04-03 06:26:30 +0000
commit283870e39be08e89050377cf2e4584b453cdc4e2 (patch)
tree9bdf769ca9cccc29e991cad418fb1f7e79f6d4ea /examples
parent382bf8f2c656e5cb52dbad4b5b66b75a2e941f5c (diff)
Add new heartrate example
The example is a redesign by Lasse Räihä based in the heartrate-listener example. Change-Id: Iec0f48603408b37c7054839d520368eb1e436895 Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
Diffstat (limited to 'examples')
-rw-r--r--examples/bluetooth/bluetooth.pro1
-rw-r--r--examples/bluetooth/heartrate-game/README.md7
-rw-r--r--examples/bluetooth/heartrate-game/bluetoothbaseclass.cpp77
-rw-r--r--examples/bluetooth/heartrate-game/bluetoothbaseclass.h72
-rw-r--r--examples/bluetooth/heartrate-game/connectionhandler.cpp71
-rw-r--r--examples/bluetooth/heartrate-game/connectionhandler.h71
-rw-r--r--examples/bluetooth/heartrate-game/devicefinder.cpp159
-rw-r--r--examples/bluetooth/heartrate-game/devicefinder.h91
-rw-r--r--examples/bluetooth/heartrate-game/devicehandler.cpp319
-rw-r--r--examples/bluetooth/heartrate-game/devicehandler.h131
-rw-r--r--examples/bluetooth/heartrate-game/deviceinfo.cpp80
-rw-r--r--examples/bluetooth/heartrate-game/deviceinfo.h69
-rw-r--r--examples/bluetooth/heartrate-game/heartrate-game.pro28
-rw-r--r--examples/bluetooth/heartrate-game/images.qrc7
-rw-r--r--examples/bluetooth/heartrate-game/main.cpp67
-rw-r--r--examples/bluetooth/heartrate-game/qml.qrc18
-rw-r--r--examples/bluetooth/heartrate-game/qml/App.qml120
-rw-r--r--examples/bluetooth/heartrate-game/qml/BluetoothAlarmDialog.qml112
-rw-r--r--examples/bluetooth/heartrate-game/qml/BottomLine.qml49
-rw-r--r--examples/bluetooth/heartrate-game/qml/Connect.qml143
-rw-r--r--examples/bluetooth/heartrate-game/qml/GameButton.qml78
-rw-r--r--examples/bluetooth/heartrate-game/qml/GamePage.qml83
-rw-r--r--examples/bluetooth/heartrate-game/qml/GameSettings.qml91
-rw-r--r--examples/bluetooth/heartrate-game/qml/Measure.qml234
-rw-r--r--examples/bluetooth/heartrate-game/qml/SplashScreen.qml80
-rw-r--r--examples/bluetooth/heartrate-game/qml/Stats.qml89
-rw-r--r--examples/bluetooth/heartrate-game/qml/StatsLabel.qml72
-rw-r--r--examples/bluetooth/heartrate-game/qml/TitleBar.qml87
-rw-r--r--examples/bluetooth/heartrate-game/qml/images/bt_off_to_on.pngbin0 -> 6143 bytes
-rw-r--r--examples/bluetooth/heartrate-game/qml/images/heart.pngbin0 -> 2664 bytes
-rw-r--r--examples/bluetooth/heartrate-game/qml/images/logo.pngbin0 -> 31915 bytes
-rw-r--r--examples/bluetooth/heartrate-game/qml/main.qml95
-rw-r--r--examples/bluetooth/heartrate-game/qml/qmldir1
33 files changed, 2602 insertions, 0 deletions
diff --git a/examples/bluetooth/bluetooth.pro b/examples/bluetooth/bluetooth.pro
index 1c09dade..39a28174 100644
--- a/examples/bluetooth/bluetooth.pro
+++ b/examples/bluetooth/bluetooth.pro
@@ -13,4 +13,5 @@ qtHaveModule(quick): SUBDIRS += scanner \
pingpong \
lowenergyscanner \
heartlistener \
+ heartrate-game \
chat
diff --git a/examples/bluetooth/heartrate-game/README.md b/examples/bluetooth/heartrate-game/README.md
new file mode 100644
index 00000000..fd7c6fd6
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/README.md
@@ -0,0 +1,7 @@
+# HeartRateGame #
+
+Demonstrates how to check a Bluetooth-connection, discover LE-devices, connect
+to devices, discover services and finally connect to a heartrate-service.
+The purpose of the game is increase the heartrate so much as possible in 60s.
+Relax before starting the game. Don't be too nervous, it increases the heartrate!
+
diff --git a/examples/bluetooth/heartrate-game/bluetoothbaseclass.cpp b/examples/bluetooth/heartrate-game/bluetoothbaseclass.cpp
new file mode 100644
index 00000000..0d7f0bbe
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/bluetoothbaseclass.cpp
@@ -0,0 +1,77 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 "bluetoothbaseclass.h"
+
+BluetoothBaseClass::BluetoothBaseClass(QObject *parent) : QObject(parent)
+{
+}
+
+QString BluetoothBaseClass::error() const
+{
+ return m_error;
+}
+
+QString BluetoothBaseClass::info() const
+{
+ return m_info;
+}
+
+void BluetoothBaseClass::setError(const QString &error)
+{
+ if (m_error != error) {
+ m_error = error;
+ emit errorChanged();
+ }
+}
+
+void BluetoothBaseClass::setInfo(const QString &info)
+{
+ if (m_info != info) {
+ m_info = info;
+ emit infoChanged();
+ }
+}
+
+void BluetoothBaseClass::clearMessages()
+{
+ setInfo("");
+ setError("");
+}
diff --git a/examples/bluetooth/heartrate-game/bluetoothbaseclass.h b/examples/bluetooth/heartrate-game/bluetoothbaseclass.h
new file mode 100644
index 00000000..ccdb60e3
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/bluetoothbaseclass.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 BLUETOOTHBASECLASS_H
+#define BLUETOOTHBASECLASS_H
+
+#include <QObject>
+
+class BluetoothBaseClass : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString error READ error WRITE setError NOTIFY errorChanged)
+ Q_PROPERTY(QString info READ info WRITE setInfo NOTIFY infoChanged)
+
+public:
+ explicit BluetoothBaseClass(QObject *parent = 0);
+
+ QString error() const;
+ void setError(const QString& error);
+
+ QString info() const;
+ void setInfo(const QString& info);
+
+ void clearMessages();
+
+signals:
+ void errorChanged();
+ void infoChanged();
+
+private:
+ QString m_error;
+ QString m_info;
+};
+
+#endif // BLUETOOTHBASECLASS_H
diff --git a/examples/bluetooth/heartrate-game/connectionhandler.cpp b/examples/bluetooth/heartrate-game/connectionhandler.cpp
new file mode 100644
index 00000000..6ca3f1d7
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/connectionhandler.cpp
@@ -0,0 +1,71 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 "connectionhandler.h"
+#include <QtDebug>
+
+ConnectionHandler::ConnectionHandler(QObject *parent) : QObject(parent)
+{
+ connect(&m_localDevice, &QBluetoothLocalDevice::hostModeStateChanged,
+ this, &ConnectionHandler::hostModeChanged);
+}
+
+bool ConnectionHandler::alive() const
+{
+#ifdef Q_OS_WIN32
+ return true;
+#else
+ return m_localDevice.isValid() && m_localDevice.hostMode() != QBluetoothLocalDevice::HostPoweredOff;
+#endif
+}
+QString ConnectionHandler::name() const
+{
+ return m_localDevice.name();
+}
+
+QString ConnectionHandler::address() const
+{
+ return m_localDevice.address().toString();
+}
+
+void ConnectionHandler::hostModeChanged(QBluetoothLocalDevice::HostMode /*mode*/)
+{
+ emit deviceChanged();
+}
diff --git a/examples/bluetooth/heartrate-game/connectionhandler.h b/examples/bluetooth/heartrate-game/connectionhandler.h
new file mode 100644
index 00000000..8c38b8ca
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/connectionhandler.h
@@ -0,0 +1,71 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 CONNECTIONHANDLER_H
+#define CONNECTIONHANDLER_H
+
+#include <QObject>
+#include <QBluetoothLocalDevice>
+
+class ConnectionHandler : public QObject
+{
+ Q_PROPERTY(bool alive READ alive NOTIFY deviceChanged)
+ Q_PROPERTY(QString name READ name NOTIFY deviceChanged)
+ Q_PROPERTY(QString address READ address NOTIFY deviceChanged)
+
+ Q_OBJECT
+public:
+ explicit ConnectionHandler(QObject *parent = 0);
+
+ bool alive() const;
+ QString name() const;
+ QString address() const;
+
+signals:
+ void deviceChanged();
+
+private slots:
+ void hostModeChanged(QBluetoothLocalDevice::HostMode mode);
+
+private:
+ QBluetoothLocalDevice m_localDevice;
+};
+
+#endif // CONNECTIONHANDLER_H
diff --git a/examples/bluetooth/heartrate-game/devicefinder.cpp b/examples/bluetooth/heartrate-game/devicefinder.cpp
new file mode 100644
index 00000000..0579ad4a
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/devicefinder.cpp
@@ -0,0 +1,159 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 "devicefinder.h"
+#include "devicehandler.h"
+#include "deviceinfo.h"
+
+#include <QBluetoothUuid>
+
+DeviceFinder::DeviceFinder(DeviceHandler *handler, QObject *parent):
+ BluetoothBaseClass(parent),
+ m_deviceHandler(handler)
+{
+ m_deviceDiscoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
+
+ connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered, this, &DeviceFinder::addDevice);
+ connect(m_deviceDiscoveryAgent, static_cast<void (QBluetoothDeviceDiscoveryAgent::*)(QBluetoothDeviceDiscoveryAgent::Error)>(&QBluetoothDeviceDiscoveryAgent::error),
+ this, &DeviceFinder::scanError);
+
+ connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished, this, &DeviceFinder::scanFinished);
+ connect(m_deviceDiscoveryAgent, &QBluetoothDeviceDiscoveryAgent::canceled, this, &DeviceFinder::scanFinished);
+
+
+#ifdef Q_OS_WIN32
+ m_demoTimer.setSingleShot(true);
+ m_demoTimer.setInterval(2000);
+ connect(&m_demoTimer, &QTimer::timeout, this, &DeviceFinder::scanFinished);
+#endif
+}
+
+DeviceFinder::~DeviceFinder()
+{
+ qDeleteAll(m_devices);
+ m_devices.clear();
+}
+
+void DeviceFinder::startSearch()
+{
+ clearMessages();
+ m_deviceHandler->setDevice(0);
+ qDeleteAll(m_devices);
+ m_devices.clear();
+
+ emit devicesChanged();
+
+#ifdef Q_OS_WIN32
+ m_demoTimer.start();
+#else
+ m_deviceDiscoveryAgent->start();
+#endif
+ emit scanningChanged();
+ setInfo(tr("Scanning for devices..."));
+}
+
+void DeviceFinder::addDevice(const QBluetoothDeviceInfo &device)
+{
+ // If device is LowEnergy-device, add it to the list
+ if (device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration) {
+ m_devices.append(new DeviceInfo(device));
+ setInfo(tr("Low Energy device found. Scanning more..."));
+ emit devicesChanged();
+ }
+}
+
+void DeviceFinder::scanError(QBluetoothDeviceDiscoveryAgent::Error error)
+{
+ if (error == QBluetoothDeviceDiscoveryAgent::PoweredOffError)
+ setError(tr("The Bluetooth adaptor is powered off."));
+ else if (error == QBluetoothDeviceDiscoveryAgent::InputOutputError)
+ setError(tr("Writing or reading from the device resulted in an error."));
+ else
+ setError(tr("An unknown error has occurred."));
+}
+
+void DeviceFinder::scanFinished()
+{
+#ifdef Q_OS_WIN32
+ // Only for testing
+ for (int i = 0; i < 5; i++)
+ m_devices.append(new DeviceInfo(QBluetoothDeviceInfo()));
+#endif
+
+ if (m_devices.size() == 0)
+ setError(tr("No Low Energy devices found."));
+ else
+ setInfo(tr("Scanning done."));
+
+ emit scanningChanged();
+ emit devicesChanged();
+}
+
+void DeviceFinder::connectToService(const QString &address)
+{
+ m_deviceDiscoveryAgent->stop();
+
+ DeviceInfo *currentDevice = 0;
+ for (int i = 0; i < m_devices.size(); i++) {
+ if (((DeviceInfo*)m_devices.at(i))->getAddress() == address ) {
+ currentDevice = (DeviceInfo*)m_devices.at(i);
+ break;
+ }
+ }
+
+ if (currentDevice)
+ m_deviceHandler->setDevice(currentDevice);
+
+ clearMessages();
+}
+
+bool DeviceFinder::scanning() const
+{
+#ifdef Q_OS_WIN32
+ return m_demoTimer.isActive();
+#else
+ return m_deviceDiscoveryAgent->isActive();
+#endif
+}
+
+QVariant DeviceFinder::devices()
+{
+ return QVariant::fromValue(m_devices);
+}
diff --git a/examples/bluetooth/heartrate-game/devicefinder.h b/examples/bluetooth/heartrate-game/devicefinder.h
new file mode 100644
index 00000000..d9ad66ad
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/devicefinder.h
@@ -0,0 +1,91 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 DEVICEFINDER_H
+#define DEVICEFINDER_H
+
+#include "bluetoothbaseclass.h"
+
+#include <QTimer>
+#include <QBluetoothDeviceDiscoveryAgent>
+#include <QBluetoothDeviceInfo>
+#include <QVariant>
+
+class DeviceInfo;
+class DeviceHandler;
+
+class DeviceFinder: public BluetoothBaseClass
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool scanning READ scanning NOTIFY scanningChanged)
+ Q_PROPERTY(QVariant devices READ devices NOTIFY devicesChanged)
+
+public:
+ DeviceFinder(DeviceHandler *handler, QObject *parent = 0);
+ ~DeviceFinder();
+
+ bool scanning() const;
+ QVariant devices();
+
+public slots:
+ void startSearch();
+ void connectToService(const QString &address);
+
+private slots:
+ void addDevice(const QBluetoothDeviceInfo&);
+ void scanError(QBluetoothDeviceDiscoveryAgent::Error error);
+ void scanFinished();
+
+signals:
+ void scanningChanged();
+ void devicesChanged();
+
+private:
+ DeviceHandler *m_deviceHandler;
+ QBluetoothDeviceDiscoveryAgent *m_deviceDiscoveryAgent;
+ QList<QObject*> m_devices;
+
+#ifdef Q_OS_WIN32
+ QTimer m_demoTimer;
+#endif
+};
+
+#endif // DEVICEFINDER_H
diff --git a/examples/bluetooth/heartrate-game/devicehandler.cpp b/examples/bluetooth/heartrate-game/devicehandler.cpp
new file mode 100644
index 00000000..da643ff5
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/devicehandler.cpp
@@ -0,0 +1,319 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 "devicehandler.h"
+#include "deviceinfo.h"
+#include <QtEndian>
+
+DeviceHandler::DeviceHandler(QObject *parent) :
+ BluetoothBaseClass(parent),
+ m_control(0),
+ m_service(0),
+ m_currentDevice(0),
+ m_foundHeartRateService(false),
+ m_measuring(false),
+ m_currentValue(0),
+ m_min(0), m_max(0), m_sum(0), m_avg(0), m_calories(0)
+{
+#ifdef Q_OS_WIN32
+ m_demoTimer.setSingleShot(false);
+ m_demoTimer.setInterval(2000);
+ connect(&m_demoTimer, &QTimer::timeout, this, &DeviceHandler::updateDemoHR);
+ m_demoTimer.start();
+ updateDemoHR();
+#endif
+}
+
+void DeviceHandler::setDevice(DeviceInfo *device)
+{
+ clearMessages();
+ m_currentDevice = device;
+
+#ifdef Q_OS_WIN32
+ setInfo(tr("Demo device connected."));
+ return;
+#endif
+
+ // Disconnect and delete old connection
+ if (m_control) {
+ m_control->disconnectFromDevice();
+ delete m_control;
+ m_control = 0;
+ }
+
+ // Create new controller and connect it if device available
+ if (m_currentDevice) {
+
+ // Make connections
+ m_control = new QLowEnergyController(m_currentDevice->getDevice(), this);
+ connect(m_control, &QLowEnergyController::serviceDiscovered,
+ this, &DeviceHandler::serviceDiscovered);
+ connect(m_control, &QLowEnergyController::discoveryFinished,
+ this, &DeviceHandler::serviceScanDone);
+
+ connect(m_control, static_cast<void (QLowEnergyController::*)(QLowEnergyController::Error)>(&QLowEnergyController::error),
+ this, [this](QLowEnergyController::Error error) {
+ Q_UNUSED(error);
+ setError("Cannot connect to remote device.");
+ });
+ connect(m_control, &QLowEnergyController::connected, this, [this]() {
+ setInfo("Controller connected. Search services...");
+ m_control->discoverServices();
+ });
+ connect(m_control, &QLowEnergyController::disconnected, this, [this]() {
+ setError("LowEnergy controller disconnected");
+ });
+
+ // Connect
+ m_control->connectToDevice();
+ }
+}
+
+void DeviceHandler::startMeasurement()
+{
+ if (alive()) {
+ m_start = QDateTime::currentDateTime();
+ m_min = 0;
+ m_max = 0;
+ m_avg = 0;
+ m_sum = 0;
+ m_calories = 0;
+ m_measuring = true;
+ m_measurements.clear();
+ emit measuringChanged();
+ }
+}
+
+void DeviceHandler::stopMeasurement()
+{
+ m_measuring = false;
+ emit measuringChanged();
+}
+
+void DeviceHandler::serviceDiscovered(const QBluetoothUuid &gatt)
+{
+ if (gatt == QBluetoothUuid(QBluetoothUuid::HeartRate)) {
+ setInfo("Heart Rate service discovered. Waiting for service scan to be done...");
+ m_foundHeartRateService = true;
+ }
+}
+
+void DeviceHandler::serviceScanDone()
+{
+ setInfo("Service scan done.");
+
+ // Delete old service if available
+ if (m_service) {
+ delete m_service;
+ m_service = 0;
+ }
+
+ // If heartRateService found, create new service
+ if (m_foundHeartRateService)
+ m_service = m_control->createServiceObject(QBluetoothUuid(QBluetoothUuid::HeartRate), this);
+
+ if (m_service) {
+ connect(m_service, &QLowEnergyService::stateChanged, this, &DeviceHandler::serviceStateChanged);
+ connect(m_service, &QLowEnergyService::characteristicChanged, this, &DeviceHandler::updateHeartRateValue);
+ connect(m_service, &QLowEnergyService::descriptorWritten, this, &DeviceHandler::confirmedDescriptorWrite);
+ m_service->discoverDetails();
+ } else {
+ setError("Heart Rate Service not found.");
+ }
+}
+
+// Service functions
+void DeviceHandler::serviceStateChanged(QLowEnergyService::ServiceState s)
+{
+ switch (s) {
+ case QLowEnergyService::DiscoveringServices:
+ setInfo(tr("Discovering services..."));
+ break;
+ case QLowEnergyService::ServiceDiscovered:
+ {
+ setInfo(tr("Service discovered."));
+
+ const QLowEnergyCharacteristic hrChar = m_service->characteristic(QBluetoothUuid(QBluetoothUuid::HeartRateMeasurement));
+ if (!hrChar.isValid()) {
+ setError("HR Data not found.");
+ break;
+ }
+
+ m_notificationDesc = hrChar.descriptor(QBluetoothUuid::ClientCharacteristicConfiguration);
+ if (m_notificationDesc.isValid())
+ m_service->writeDescriptor(m_notificationDesc, QByteArray::fromHex("0100"));
+
+ break;
+ }
+ default:
+ //nothing for now
+ break;
+ }
+
+ emit aliveChanged();
+}
+
+void DeviceHandler::updateHeartRateValue(const QLowEnergyCharacteristic &c, const QByteArray &value)
+{
+ // ignore any other characteristic change -> shouldn't really happen though
+ if (c.uuid() != QBluetoothUuid(QBluetoothUuid::HeartRateMeasurement))
+ return;
+
+ const quint8 *data = reinterpret_cast<const quint8 *>(value.constData());
+ quint8 flags = data[0];
+
+ //Heart Rate
+ int hrvalue = 0;
+ if (flags & 0x1) // HR 16 bit? otherwise 8 bit
+ hrvalue = (int)qFromLittleEndian<quint16>(data[1]);
+ else
+ hrvalue = (int)data[1];
+
+ addMeasurement(hrvalue);
+}
+
+#ifdef Q_OS_WIN32
+void DeviceHandler::updateDemoHR()
+{
+ int randomValue = 0;
+ if (m_currentValue < 30) { // Initial value
+ randomValue = 55 + qrand()%30;
+ } else if (!m_measuring) { // Value when relax
+ randomValue = qBound(55, m_currentValue - 2 + qrand()%5, 75);
+ } else { // Measuring
+ randomValue = m_currentValue + qrand()%10 - 2;
+ }
+
+ addMeasurement(randomValue);
+}
+#endif
+
+void DeviceHandler::confirmedDescriptorWrite(const QLowEnergyDescriptor &d, const QByteArray &value)
+{
+ if (d.isValid() && d == m_notificationDesc && value == QByteArray("0000")) {
+ //disabled notifications -> assume disconnect intent
+ m_control->disconnectFromDevice();
+ delete m_service;
+ m_service = 0;
+ }
+}
+
+void DeviceHandler::disconnectService()
+{
+ m_foundHeartRateService = false;
+
+ //disable notifications
+ if (m_notificationDesc.isValid() && m_service) {
+ m_service->writeDescriptor(m_notificationDesc, QByteArray::fromHex("0000"));
+ } else {
+ if (m_control)
+ m_control->disconnectFromDevice();
+
+ delete m_service;
+ m_service = 0;
+ }
+}
+
+bool DeviceHandler::measuring() const
+{
+ return m_measuring;
+}
+
+bool DeviceHandler::alive() const
+{
+#ifdef Q_OS_WIN32
+ return true;
+#endif
+
+ if (m_service)
+ return m_service->state() == QLowEnergyService::ServiceDiscovered;
+
+ return false;
+}
+
+int DeviceHandler::hr() const
+{
+ return m_currentValue;
+}
+
+int DeviceHandler::time() const
+{
+ return m_start.secsTo(m_stop);
+}
+
+int DeviceHandler::maxHR() const
+{
+ return m_max;
+}
+
+int DeviceHandler::minHR() const
+{
+ return m_min;
+}
+
+float DeviceHandler::average() const
+{
+ return m_avg;
+}
+
+float DeviceHandler::calories() const
+{
+ return m_calories;
+}
+
+void DeviceHandler::addMeasurement(int value)
+{
+ m_currentValue = value;
+
+ // If measuring and value is appropriate
+ if (m_measuring && value > 30 && value < 250) {
+
+ m_stop = QDateTime::currentDateTime();
+ m_measurements << value;
+
+ m_min = m_min == 0 ? value : qMin(value, m_min);
+ m_max = qMax(value, m_max);
+ m_sum += value;
+ m_avg = (double)m_sum / m_measurements.size();
+ m_calories = ((-55.0969 + (0.6309 * m_avg) + (0.1988 * 94) + (0.2017 * 24)) / 4.184) * 60 * time()/3600;
+ }
+
+ emit statsChanged();
+}
diff --git a/examples/bluetooth/heartrate-game/devicehandler.h b/examples/bluetooth/heartrate-game/devicehandler.h
new file mode 100644
index 00000000..d00f0406
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/devicehandler.h
@@ -0,0 +1,131 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 DEVICEHANDLER_H
+#define DEVICEHANDLER_H
+
+#include "bluetoothbaseclass.h"
+
+#include <QDateTime>
+#include <QVector>
+#include <QTimer>
+#include <QLowEnergyController>
+#include <QLowEnergyService>
+
+class DeviceInfo;
+
+class DeviceHandler : public BluetoothBaseClass
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool measuring READ measuring NOTIFY measuringChanged)
+ Q_PROPERTY(bool alive READ alive NOTIFY aliveChanged)
+ Q_PROPERTY(int hr READ hr NOTIFY statsChanged)
+ Q_PROPERTY(int maxHR READ maxHR NOTIFY statsChanged)
+ Q_PROPERTY(int minHR READ minHR NOTIFY statsChanged)
+ Q_PROPERTY(float average READ average NOTIFY statsChanged)
+ Q_PROPERTY(int time READ time NOTIFY statsChanged)
+ Q_PROPERTY(float calories READ calories NOTIFY statsChanged)
+
+public:
+ DeviceHandler(QObject *parent = 0);
+
+ void setDevice(DeviceInfo *device);
+ bool measuring() const;
+ bool alive() const;
+
+ // Statistics
+ int hr() const;
+ int time() const;
+ float average() const;
+ int maxHR() const;
+ int minHR() const;
+ float calories() const;
+
+signals:
+ void measuringChanged();
+ void aliveChanged();
+ void statsChanged();
+
+public slots:
+ void startMeasurement();
+ void stopMeasurement();
+ void disconnectService();
+
+private:
+ //QLowEnergyController
+ void serviceDiscovered(const QBluetoothUuid &);
+ void serviceScanDone();
+
+ //QLowEnergyService
+ void serviceStateChanged(QLowEnergyService::ServiceState s);
+ void updateHeartRateValue(const QLowEnergyCharacteristic &c,
+ const QByteArray &value);
+ void confirmedDescriptorWrite(const QLowEnergyDescriptor &d,
+ const QByteArray &value);
+
+#ifdef Q_OS_WIN32
+ void updateDemoHR();
+#endif
+private:
+ void addMeasurement(int value);
+
+ QLowEnergyController *m_control;
+ QLowEnergyService *m_service;
+ QLowEnergyDescriptor m_notificationDesc;
+ DeviceInfo *m_currentDevice;
+
+ bool m_foundHeartRateService;
+ bool m_measuring;
+ int m_currentValue, m_min, m_max, m_sum;
+ float m_avg, m_calories;
+
+ // Statistics
+ QDateTime m_start;
+ QDateTime m_stop;
+
+ QVector<int> m_measurements;
+
+#ifdef Q_OS_WIN32
+ QTimer m_demoTimer;
+#endif
+};
+
+#endif // DEVICEHANDLER_H
diff --git a/examples/bluetooth/heartrate-game/deviceinfo.cpp b/examples/bluetooth/heartrate-game/deviceinfo.cpp
new file mode 100644
index 00000000..4d1a3498
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/deviceinfo.cpp
@@ -0,0 +1,80 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 "deviceinfo.h"
+#include <QBluetoothAddress>
+#include <QBluetoothUuid>
+
+DeviceInfo::DeviceInfo(const QBluetoothDeviceInfo &info):
+ QObject(), m_device(info)
+{
+}
+
+QBluetoothDeviceInfo DeviceInfo::getDevice() const
+{
+ return m_device;
+}
+
+QString DeviceInfo::getName() const
+{
+#ifdef Q_OS_WIN32
+ return "Demo device";
+#else
+ return m_device.name();
+#endif
+}
+
+QString DeviceInfo::getAddress() const
+{
+#ifdef Q_OS_WIN32
+ return "00:11:22:33:44:55";
+#elif Q_OS_DARWIN
+ // workaround for Core Bluetooth:
+ return m_device.deviceUuid().toString();
+#else
+ return m_device.address().toString();
+#endif
+}
+
+void DeviceInfo::setDevice(const QBluetoothDeviceInfo &device)
+{
+ m_device = device;
+ emit deviceChanged();
+}
diff --git a/examples/bluetooth/heartrate-game/deviceinfo.h b/examples/bluetooth/heartrate-game/deviceinfo.h
new file mode 100644
index 00000000..bbddbdd4
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/deviceinfo.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 DEVICEINFO_H
+#define DEVICEINFO_H
+
+#include <QString>
+#include <QObject>
+#include <QBluetoothDeviceInfo>
+
+class DeviceInfo: public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString deviceName READ getName NOTIFY deviceChanged)
+ Q_PROPERTY(QString deviceAddress READ getAddress NOTIFY deviceChanged)
+
+public:
+ DeviceInfo(const QBluetoothDeviceInfo &device);
+
+ void setDevice(const QBluetoothDeviceInfo &device);
+ QString getName() const;
+ QString getAddress() const;
+ QBluetoothDeviceInfo getDevice() const;
+
+signals:
+ void deviceChanged();
+
+private:
+ QBluetoothDeviceInfo m_device;
+};
+
+#endif // DEVICEINFO_H
diff --git a/examples/bluetooth/heartrate-game/heartrate-game.pro b/examples/bluetooth/heartrate-game/heartrate-game.pro
new file mode 100644
index 00000000..5a856b9c
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/heartrate-game.pro
@@ -0,0 +1,28 @@
+TEMPLATE = app
+TARGET = heartrate-game
+
+QT += qml quick bluetooth
+CONFIG += c++11
+
+HEADERS += \
+ connectionhandler.h \
+ deviceinfo.h \
+ devicefinder.h \
+ devicehandler.h \
+ bluetoothbaseclass.h
+
+SOURCES += main.cpp \
+ connectionhandler.cpp \
+ deviceinfo.cpp \
+ devicefinder.cpp \
+ devicehandler.cpp \
+ bluetoothbaseclass.cpp
+
+RESOURCES += qml.qrc \
+ images.qrc
+
+# Additional import path used to resolve QML modules in Qt Creator's code model
+QML_IMPORT_PATH =
+
+target.path = $$[QT_INSTALL_EXAMPLES]/bluetooth/heartrate-game
+INSTALLS += target
diff --git a/examples/bluetooth/heartrate-game/images.qrc b/examples/bluetooth/heartrate-game/images.qrc
new file mode 100644
index 00000000..38058de0
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/images.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qml/images/logo.png</file>
+ <file>qml/images/bt_off_to_on.png</file>
+ <file>qml/images/heart.png</file>
+ </qresource>
+</RCC>
diff --git a/examples/bluetooth/heartrate-game/main.cpp b/examples/bluetooth/heartrate-game/main.cpp
new file mode 100644
index 00000000..039b0668
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/main.cpp
@@ -0,0 +1,67 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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 <QGuiApplication>
+#include <QQmlApplicationEngine>
+#include <QQmlContext>
+#include <QtCore/QLoggingCategory>
+
+#include "connectionhandler.h"
+#include "devicefinder.h"
+#include "devicehandler.h"
+
+int main(int argc, char *argv[])
+{
+ //QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true"));
+ QGuiApplication app(argc, argv);
+
+ ConnectionHandler connectionHandler;
+ DeviceHandler deviceHandler;
+ DeviceFinder deviceFinder(&deviceHandler);
+
+ QQmlApplicationEngine engine;
+ engine.rootContext()->setContextProperty("connectionHandler", &connectionHandler);
+ engine.rootContext()->setContextProperty("deviceFinder", &deviceFinder);
+ engine.rootContext()->setContextProperty("deviceHandler", &deviceHandler);
+
+ engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
+
+ return app.exec();
+}
diff --git a/examples/bluetooth/heartrate-game/qml.qrc b/examples/bluetooth/heartrate-game/qml.qrc
new file mode 100644
index 00000000..bab96355
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml.qrc
@@ -0,0 +1,18 @@
+<RCC>
+ <qresource prefix="/">
+ <file>qml/BluetoothAlarmDialog.qml</file>
+ <file>qml/main.qml</file>
+ <file>qml/SplashScreen.qml</file>
+ <file>qml/GameSettings.qml</file>
+ <file>qml/App.qml</file>
+ <file>qml/TitleBar.qml</file>
+ <file>qml/Connect.qml</file>
+ <file>qml/Measure.qml</file>
+ <file>qml/Stats.qml</file>
+ <file>qml/GameButton.qml</file>
+ <file>qml/GamePage.qml</file>
+ <file>qml/BottomLine.qml</file>
+ <file>qml/StatsLabel.qml</file>
+ <file>qml/qmldir</file>
+ </qresource>
+</RCC>
diff --git a/examples/bluetooth/heartrate-game/qml/App.qml b/examples/bluetooth/heartrate-game/qml/App.qml
new file mode 100644
index 00000000..fc8b1c89
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/App.qml
@@ -0,0 +1,120 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+
+Item {
+ id: app
+ anchors.fill: parent
+ opacity: 0.0
+
+ Behavior on opacity { NumberAnimation { duration: 500 } }
+
+ property var lastPages: []
+ property int __currentIndex: 0
+
+ function init()
+ {
+ opacity = 1.0
+ showPage("Connect.qml")
+ }
+
+ function prevPage()
+ {
+ lastPages.pop()
+ pageLoader.setSource(lastPages[lastPages.length-1])
+ __currentIndex = lastPages.length-1;
+ }
+
+ function showPage(name)
+ {
+ lastPages.push(name)
+ pageLoader.setSource(name)
+ __currentIndex = lastPages.length-1;
+ }
+
+ TitleBar {
+ id: titleBar
+ currentIndex: __currentIndex
+
+ onTitleClicked: {
+ if (index < __currentIndex)
+ pageLoader.item.close()
+ }
+ }
+
+ Loader {
+ id: pageLoader
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: titleBar.bottom
+ anchors.bottom: parent.bottom
+
+ onStatusChanged: {
+ if (status === Loader.Ready)
+ {
+ pageLoader.item.init();
+ pageLoader.item.forceActiveFocus()
+ }
+ }
+ }
+
+ Keys.onReleased: {
+ switch (event.key) {
+ case Qt.Key_Escape:
+ case Qt.Key_Back: {
+ if (__currentIndex > 0) {
+ pageLoader.item.close()
+ event.accepted = true
+ } else {
+ Qt.quit()
+ }
+ break;
+ }
+ default: break;
+ }
+ }
+
+ BluetoothAlarmDialog {
+ id: btAlarmDialog
+ anchors.fill: parent
+ visible: !connectionHandler.alive
+ }
+}
diff --git a/examples/bluetooth/heartrate-game/qml/BluetoothAlarmDialog.qml b/examples/bluetooth/heartrate-game/qml/BluetoothAlarmDialog.qml
new file mode 100644
index 00000000..ef32f5ea
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/BluetoothAlarmDialog.qml
@@ -0,0 +1,112 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+
+Item {
+ id: root
+ anchors.fill: parent
+
+ Rectangle {
+ anchors.fill: parent
+ color: "black"
+ opacity: 0.9
+ }
+
+ MouseArea {
+ id: eventEater
+ }
+
+ Rectangle {
+ id: dialogFrame
+
+ anchors.centerIn: parent
+ width: parent.width * 0.8
+ height: parent.height * 0.6
+ border.color: "#454545"
+ color: GameSettings.backgroundColor
+ radius: width * 0.05
+
+ Item {
+ id: dialogContainer
+ anchors.fill: parent
+ anchors.margins: parent.width*0.05
+
+ Image {
+ id: offOnImage
+ anchors.left: quitButton.left
+ anchors.right: quitButton.right
+ anchors.top: parent.top
+ height: GameSettings.heightForWidth(width, sourceSize)
+ source: "images/bt_off_to_on.png"
+ }
+
+ Text {
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.top: offOnImage.bottom
+ anchors.bottom: quitButton.top
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ wrapMode: Text.WordWrap
+ font.pixelSize: GameSettings.mediumFontSize
+ color: GameSettings.textColor
+ text: qsTr("This application cannot be used without Bluetooth. Please switch Bluetooth ON to continue.")
+ }
+
+ GameButton {
+ id: quitButton
+ anchors.bottom: parent.bottom
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: dialogContainer.width * 0.6
+ height: GameSettings.buttonHeight
+ onClicked: Qt.quit()
+
+ Text {
+ anchors.centerIn: parent
+ color: GameSettings.textColor
+ font.pixelSize: GameSettings.bigFontSize
+ text: qsTr("Quit")
+ }
+ }
+ }
+ }
+}
+
diff --git a/examples/bluetooth/heartrate-game/qml/BottomLine.qml b/examples/bluetooth/heartrate-game/qml/BottomLine.qml
new file mode 100644
index 00000000..af644228
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/BottomLine.qml
@@ -0,0 +1,49 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+
+Rectangle {
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ width: parent.width * 0.85
+ height: parent.height * 0.05
+ radius: height*0.5
+}
diff --git a/examples/bluetooth/heartrate-game/qml/Connect.qml b/examples/bluetooth/heartrate-game/qml/Connect.qml
new file mode 100644
index 00000000..d3b4a733
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/Connect.qml
@@ -0,0 +1,143 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+
+GamePage {
+
+ errorMessage: deviceFinder.error
+ infoMessage: deviceFinder.info
+
+ Rectangle {
+ id: viewContainer
+ anchors.top: parent.top
+ anchors.bottom: searchButton.top
+ anchors.topMargin: GameSettings.fieldMargin + messageHeight
+ anchors.bottomMargin: GameSettings.fieldMargin
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: parent.width - GameSettings.fieldMargin*2
+ color: GameSettings.viewColor
+ radius: GameSettings.buttonRadius
+
+
+ Text {
+ id: title
+ width: parent.width
+ height: GameSettings.fieldHeight
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ color: GameSettings.textColor
+ font.pixelSize: GameSettings.mediumFontSize
+ text: qsTr("FOUND DEVICES")
+
+ BottomLine {
+ height: 1;
+ width: parent.width
+ color: "#898989"
+ }
+ }
+
+
+ ListView {
+ id: devices
+ anchors.left: parent.left
+ anchors.right: parent.right
+ anchors.bottom: parent.bottom
+ anchors.top: title.bottom
+ model: deviceFinder.devices
+ clip: true
+
+ delegate: Rectangle {
+ id: box
+ height:GameSettings.fieldHeight * 1.2
+ width: parent.width
+ color: index % 2 === 0 ? GameSettings.delegate1Color : GameSettings.delegate2Color
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ deviceFinder.connectToService(modelData.deviceAddress);
+ app.showPage("Measure.qml")
+ }
+ }
+
+ Text {
+ id: device
+ font.pixelSize: GameSettings.smallFontSize
+ text: modelData.deviceName
+ anchors.top: parent.top
+ anchors.topMargin: parent.height * 0.1
+ anchors.leftMargin: parent.height * 0.1
+ anchors.left: parent.left
+ color: GameSettings.textColor
+ }
+
+ Text {
+ id: deviceAddress
+ font.pixelSize: GameSettings.smallFontSize
+ text: modelData.deviceAddress
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: parent.height * 0.1
+ anchors.rightMargin: parent.height * 0.1
+ anchors.right: parent.right
+ color: Qt.darker(GameSettings.textColor)
+ }
+ }
+ }
+ }
+
+ GameButton {
+ id: searchButton
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: GameSettings.fieldMargin
+ width: viewContainer.width
+ height: GameSettings.fieldHeight
+ enabled: !deviceFinder.scanning
+ onClicked: deviceFinder.startSearch()
+
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: GameSettings.tinyFontSize
+ text: qsTr("START SEARCH")
+ color: searchButton.enabled ? GameSettings.textColor : GameSettings.disabledTextColor
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate-game/qml/GameButton.qml b/examples/bluetooth/heartrate-game/qml/GameButton.qml
new file mode 100644
index 00000000..e7fc36af
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/GameButton.qml
@@ -0,0 +1,78 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+import "."
+
+Rectangle {
+ id: button
+ color: baseColor
+ onEnabledChanged: checkColor()
+ radius: GameSettings.buttonRadius
+
+ property color baseColor: GameSettings.buttonColor
+ property color pressedColor: GameSettings.buttonPressedColor
+ property color disabledColor: GameSettings.disabledButtonColor
+
+ signal clicked()
+
+ function checkColor()
+ {
+ if (!button.enabled) {
+ button.color = disabledColor
+ } else {
+ if (mouseArea.containsPress)
+ button.color = pressedColor
+ else
+ button.color = baseColor
+ }
+ }
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ onPressed: checkColor()
+ onReleased: checkColor()
+ onClicked: {
+ checkColor()
+ button.clicked()
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate-game/qml/GamePage.qml b/examples/bluetooth/heartrate-game/qml/GamePage.qml
new file mode 100644
index 00000000..663eb047
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/GamePage.qml
@@ -0,0 +1,83 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+import "."
+
+Item {
+ anchors.fill: parent
+
+ property string errorMessage: ""
+ property string infoMessage: ""
+ property real messageHeight: msg.height
+ property bool hasError: errorMessage != ""
+ property bool hasInfo: infoMessage != ""
+
+ function init()
+ {
+ }
+
+ function close()
+ {
+ app.prevPage()
+ }
+
+ Rectangle {
+ id: msg
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: GameSettings.fieldHeight
+ color: hasError ? GameSettings.errorColor : GameSettings.infoColor
+ visible: hasError || hasInfo
+
+ Text {
+ id: error
+ anchors.fill: parent
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ minimumPixelSize: 5
+ font.pixelSize: GameSettings.smallFontSize
+ fontSizeMode: Text.Fit
+ color: GameSettings.textColor
+ text: hasError ? errorMessage : infoMessage
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate-game/qml/GameSettings.qml b/examples/bluetooth/heartrate-game/qml/GameSettings.qml
new file mode 100644
index 00000000..868f32ac
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/GameSettings.qml
@@ -0,0 +1,91 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+pragma Singleton
+import QtQuick 2.5
+
+Item {
+ property int wHeight
+ property int wWidth
+
+ // Colors
+ readonly property color backgroundColor: "#2d3037"
+ readonly property color buttonColor: "#202227"
+ readonly property color buttonPressedColor: "#6ccaf2"
+ readonly property color disabledButtonColor: "#555555"
+ readonly property color viewColor: "#202227"
+ readonly property color delegate1Color: Qt.darker(viewColor, 1.2)
+ readonly property color delegate2Color: Qt.lighter(viewColor, 1.2)
+ readonly property color textColor: "#ffffff"
+ readonly property color textDarkColor: "#232323"
+ readonly property color disabledTextColor: "#777777"
+ readonly property color sliderColor: "#6ccaf2"
+ readonly property color errorColor: "#ba3f62"
+ readonly property color infoColor: "#3fba62"
+
+ // Font sizes
+ property real microFontSize: hugeFontSize * 0.2
+ property real tinyFontSize: hugeFontSize * 0.4
+ property real smallTinyFontSize: hugeFontSize * 0.5
+ property real smallFontSize: hugeFontSize * 0.6
+ property real mediumFontSize: hugeFontSize * 0.7
+ property real bigFontSize: hugeFontSize * 0.8
+ property real largeFontSize: hugeFontSize * 0.9
+ property real hugeFontSize: (wWidth + wHeight) * 0.03
+ property real giganticFontSize: (wWidth + wHeight) * 0.04
+
+ // Some other values
+ property real fieldHeight: wHeight * 0.08
+ property real fieldMargin: fieldHeight * 0.5
+ property real buttonHeight: wHeight * 0.08
+ property real buttonRadius: buttonHeight * 0.1
+
+ // Some help functions
+ function widthForHeight(h, ss)
+ {
+ return h/ss.height * ss.width;
+ }
+
+ function heightForWidth(w, ss)
+ {
+ return w/ss.width * ss.height;
+ }
+
+}
diff --git a/examples/bluetooth/heartrate-game/qml/Measure.qml b/examples/bluetooth/heartrate-game/qml/Measure.qml
new file mode 100644
index 00000000..f8c51eb4
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/Measure.qml
@@ -0,0 +1,234 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+
+GamePage {
+ id: measurePage
+
+ errorMessage: deviceHandler.error
+ infoMessage: deviceHandler.info
+
+ property real __timeCounter: 0;
+ property real __maxTimeCount: 60
+ property string relaxText: qsTr("Relax!\nWhen you are ready, press Start. You have %1s time to increase heartrate so much as possible.\nGood luck!").arg(__maxTimeCount)
+
+ function close()
+ {
+ deviceHandler.stopMeasurement();
+ deviceHandler.disconnectService();
+ app.prevPage();
+ }
+
+ function start()
+ {
+ if (!deviceHandler.measuring) {
+ __timeCounter = 0;
+ deviceHandler.startMeasurement()
+ }
+ }
+
+ function stop()
+ {
+ if (deviceHandler.measuring) {
+ deviceHandler.stopMeasurement()
+ }
+
+ app.showPage("Stats.qml")
+ }
+
+ Timer {
+ id: measureTimer
+ interval: 1000
+ running: deviceHandler.measuring
+ repeat: true
+ onTriggered: {
+ __timeCounter++;
+ if (__timeCounter >= __maxTimeCount)
+ measurePage.stop()
+ }
+ }
+
+ Column {
+ anchors.centerIn: parent
+ spacing: GameSettings.fieldHeight * 0.5
+
+ Rectangle {
+ id: circle
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: Math.min(measurePage.width, measurePage.height-GameSettings.fieldHeight*4) - 2*GameSettings.fieldMargin
+ height: width
+ radius: width*0.5
+ color: GameSettings.viewColor
+
+ Text {
+ id: hintText
+ anchors.centerIn: parent
+ anchors.verticalCenterOffset: -parent.height*0.1
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ width: parent.width * 0.8
+ height: parent.height * 0.6
+ wrapMode: Text.WordWrap
+ text: measurePage.relaxText
+ visible: !deviceHandler.measuring
+ color: GameSettings.textColor
+ fontSizeMode: Text.Fit
+ minimumPixelSize: 10
+ font.pixelSize: GameSettings.mediumFontSize
+ }
+
+ Text {
+ id: text
+ anchors.centerIn: parent
+ anchors.verticalCenterOffset: -parent.height*0.15
+ font.pixelSize: parent.width * 0.45
+ text: deviceHandler.hr
+ visible: deviceHandler.measuring
+ color: GameSettings.textColor
+ }
+
+ Item {
+ id: minMaxContainer
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: parent.width*0.7
+ height: parent.height * 0.15
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: parent.height*0.16
+ visible: deviceHandler.measuring
+
+ Text {
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ text: deviceHandler.minHR
+ color: GameSettings.textColor
+ font.pixelSize: GameSettings.hugeFontSize
+
+ Text {
+ anchors.left: parent.left
+ anchors.bottom: parent.top
+ font.pixelSize: parent.font.pixelSize*0.8
+ color: parent.color
+ text: "MIN"
+ }
+ }
+
+ Text {
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ text: deviceHandler.maxHR
+ color: GameSettings.textColor
+ font.pixelSize: GameSettings.hugeFontSize
+
+ Text {
+ anchors.right: parent.right
+ anchors.bottom: parent.top
+ font.pixelSize: parent.font.pixelSize*0.8
+ color: parent.color
+ text: "MAX"
+ }
+ }
+ }
+
+ Image {
+ id: heart
+ anchors.horizontalCenter: minMaxContainer.horizontalCenter
+ anchors.verticalCenter: minMaxContainer.bottom
+ width: parent.width * 0.2
+ height: width
+ source: "images/heart.png"
+ smooth: true
+ antialiasing: true
+
+ SequentialAnimation{
+ id: heartAnim
+ running: deviceHandler.alive
+ loops: Animation.Infinite
+ alwaysRunToEnd: true
+ PropertyAnimation { target: heart; property: "scale"; to: 1.2; duration: 500; easing.type: Easing.InQuad }
+ PropertyAnimation { target: heart; property: "scale"; to: 1.0; duration: 500; easing.type: Easing.OutQuad }
+ }
+ }
+ }
+
+ Rectangle {
+ id: timeSlider
+ color: GameSettings.viewColor
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: circle.width
+ height: GameSettings.fieldHeight
+ radius: GameSettings.buttonRadius
+
+ Rectangle {
+ height: parent.height
+ radius: parent.radius
+ color: GameSettings.sliderColor
+ width: Math.min(1.0,__timeCounter / __maxTimeCount) * parent.width
+ }
+
+ Text {
+ anchors.centerIn: parent
+ color: "gray"
+ text: (__maxTimeCount - __timeCounter).toFixed(0) + " s"
+ font.pixelSize: GameSettings.bigFontSize
+ }
+ }
+ }
+
+ GameButton {
+ id: startButton
+ anchors.horizontalCenter: parent.horizontalCenter
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: GameSettings.fieldMargin
+ width: circle.width
+ height: GameSettings.fieldHeight
+ enabled: !deviceHandler.measuring
+ radius: GameSettings.buttonRadius
+
+ onClicked: start()
+
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: GameSettings.tinyFontSize
+ text: qsTr("START")
+ color: startButton.enabled ? GameSettings.textColor : GameSettings.disabledTextColor
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate-game/qml/SplashScreen.qml b/examples/bluetooth/heartrate-game/qml/SplashScreen.qml
new file mode 100644
index 00000000..f480125e
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/SplashScreen.qml
@@ -0,0 +1,80 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+import "."
+
+Item {
+ id: root
+ anchors.fill: parent
+
+ property bool appIsReady: false
+ property bool splashIsReady: false
+
+ property bool ready: appIsReady && splashIsReady
+ onReadyChanged: if (ready) readyToGo();
+
+ signal readyToGo()
+
+ function appReady()
+ {
+ appIsReady = true
+ }
+
+ function errorInLoadingApp()
+ {
+ Qt.quit()
+ }
+
+ Image {
+ anchors.centerIn: parent
+ width: Math.min(parent.height, parent.width)*0.6
+ height: GameSettings.heightForWidth(width, sourceSize)
+ source: "images/logo.png"
+ }
+
+ Timer {
+ id: splashTimer
+ interval: 1000
+ onTriggered: splashIsReady = true
+ }
+
+ Component.onCompleted: splashTimer.start()
+}
diff --git a/examples/bluetooth/heartrate-game/qml/Stats.qml b/examples/bluetooth/heartrate-game/qml/Stats.qml
new file mode 100644
index 00000000..6e34d3bc
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/Stats.qml
@@ -0,0 +1,89 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+
+GamePage {
+
+ Column {
+ anchors.centerIn: parent
+ width: parent.width
+
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ font.pixelSize: GameSettings.hugeFontSize
+ color: GameSettings.textColor
+ text: qsTr("RESULT")
+ }
+
+ Text {
+ anchors.horizontalCenter: parent.horizontalCenter
+ font.pixelSize: GameSettings.giganticFontSize*3
+ color: GameSettings.textColor
+ text: (deviceHandler.maxHR - deviceHandler.minHR).toFixed(0)
+ }
+
+ Item {
+ height: GameSettings.fieldHeight
+ width: 1
+ }
+
+ StatsLabel {
+ title: qsTr("MIN")
+ value: deviceHandler.minHR.toFixed(0)
+ }
+
+ StatsLabel {
+ title: qsTr("MAX")
+ value: deviceHandler.maxHR.toFixed(0)
+ }
+
+ StatsLabel {
+ title: qsTr("AVG")
+ value: deviceHandler.average.toFixed(1)
+ }
+
+
+ StatsLabel {
+ title: qsTr("CALORIES")
+ value: deviceHandler.calories.toFixed(3)
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate-game/qml/StatsLabel.qml b/examples/bluetooth/heartrate-game/qml/StatsLabel.qml
new file mode 100644
index 00000000..dd57852f
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/StatsLabel.qml
@@ -0,0 +1,72 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+import "."
+
+Item {
+ height: GameSettings.fieldHeight
+ width: parent.width
+
+ property alias title: leftText.text
+ property alias value: rightText.text
+
+ Text {
+ id: leftText
+ anchors.left: parent.left
+ height: parent.height
+ width: parent.width * 0.45
+ horizontalAlignment: Text.AlignRight
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: GameSettings.mediumFontSize
+ color: GameSettings.textColor
+ }
+
+ Text {
+ id: rightText
+ anchors.right: parent.right
+ height: parent.height
+ width: parent.width * 0.45
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ font.pixelSize: GameSettings.mediumFontSize
+ color: GameSettings.textColor
+ }
+}
diff --git a/examples/bluetooth/heartrate-game/qml/TitleBar.qml b/examples/bluetooth/heartrate-game/qml/TitleBar.qml
new file mode 100644
index 00000000..46d641e6
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/TitleBar.qml
@@ -0,0 +1,87 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.5
+
+Rectangle {
+ id: titleBar
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ height: GameSettings.fieldHeight
+ color: GameSettings.viewColor
+
+ property var __titles: ["CONNECT", "MEASURE", "STATS"]
+ property int currentIndex: 0
+
+ signal titleClicked(int index)
+
+ Repeater {
+ model: 3
+ Text {
+ width: titleBar.width / 3
+ height: titleBar.height
+ x: index * width
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: __titles[index]
+ font.pixelSize: GameSettings.tinyFontSize
+ color: titleBar.currentIndex === index ? GameSettings.textColor : GameSettings.disabledTextColor
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: titleClicked(index)
+ }
+ }
+ }
+
+
+ Item {
+ anchors.bottom: parent.bottom
+ width: parent.width / 3
+ height: parent.height
+ x: currentIndex * width
+
+ BottomLine{}
+
+ Behavior on x { NumberAnimation { duration: 200 } }
+ }
+
+}
diff --git a/examples/bluetooth/heartrate-game/qml/images/bt_off_to_on.png b/examples/bluetooth/heartrate-game/qml/images/bt_off_to_on.png
new file mode 100644
index 00000000..5ea1f3f0
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/images/bt_off_to_on.png
Binary files differ
diff --git a/examples/bluetooth/heartrate-game/qml/images/heart.png b/examples/bluetooth/heartrate-game/qml/images/heart.png
new file mode 100644
index 00000000..f2b3c0a3
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/images/heart.png
Binary files differ
diff --git a/examples/bluetooth/heartrate-game/qml/images/logo.png b/examples/bluetooth/heartrate-game/qml/images/logo.png
new file mode 100644
index 00000000..ea0af7e0
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/images/logo.png
Binary files differ
diff --git a/examples/bluetooth/heartrate-game/qml/main.qml b/examples/bluetooth/heartrate-game/qml/main.qml
new file mode 100644
index 00000000..66649a7a
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/main.qml
@@ -0,0 +1,95 @@
+/***************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the examples of the QtBluetooth module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** 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.7
+import QtQuick.Window 2.2
+import "."
+
+Window {
+ id: wroot
+ visible: true
+ width: 720 * .7
+ height: 1240 * .7
+ title: qsTr("HeartRateGame")
+ color: GameSettings.backgroundColor
+
+ Component.onCompleted: {
+ GameSettings.wWidth = Qt.binding(function() {return width})
+ GameSettings.wHeight = Qt.binding(function() {return height})
+ }
+
+ Loader {
+ id: splashLoader
+ anchors.fill: parent
+ source: "SplashScreen.qml"
+ asynchronous: false
+ visible: true
+
+ onStatusChanged: {
+ if (status === Loader.Ready) {
+ appLoader.setSource("App.qml");
+ }
+ }
+ }
+
+ Connections {
+ target: splashLoader.item
+ onReadyToGo: {
+ appLoader.visible = true
+ appLoader.item.init()
+ splashLoader.visible = false
+ splashLoader.setSource("")
+ appLoader.item.forceActiveFocus();
+ }
+ }
+
+ Loader {
+ id: appLoader
+ anchors.fill: parent
+ visible: false
+ asynchronous: true
+ onStatusChanged: {
+ if (status === Loader.Ready)
+ splashLoader.item.appReady()
+ if (status === Loader.Error)
+ splashLoader.item.errorInLoadingApp();
+ }
+ }
+}
diff --git a/examples/bluetooth/heartrate-game/qml/qmldir b/examples/bluetooth/heartrate-game/qml/qmldir
new file mode 100644
index 00000000..5e0d2b54
--- /dev/null
+++ b/examples/bluetooth/heartrate-game/qml/qmldir
@@ -0,0 +1 @@
+singleton GameSettings 1.0 GameSettings.qml