aboutsummaryrefslogtreecommitdiffstats
path: root/examples/bluetooth
diff options
context:
space:
mode:
Diffstat (limited to 'examples/bluetooth')
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/BluetoothAlarmDialog.qml6
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/BottomLine.qml3
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/Connect.qml70
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/GamePage.qml54
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/GameSettings.qml60
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/Measure.qml231
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/SplashScreen.qml2
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/Stats.qml45
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/TitleBar.qml57
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/alert.svg4
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/bluetooth.svg3
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/clock.svg4
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/heart.pngbin2664 -> 2318 bytes
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/progress.svg4
-rw-r--r--examples/bluetooth/heartrate_game/HeartRateGame/images/search.svg4
-rw-r--r--examples/bluetooth/heartrate_game/bluetoothbaseclass.py31
-rw-r--r--examples/bluetooth/heartrate_game/devicefinder.py17
-rw-r--r--examples/bluetooth/heartrate_game/devicehandler.py22
-rw-r--r--examples/bluetooth/heartrate_game/deviceinfo.py2
-rw-r--r--examples/bluetooth/heartrate_game/doc/heartrate_game.rst3
-rw-r--r--examples/bluetooth/heartrate_game/heartrate_global.py1
-rw-r--r--examples/bluetooth/heartrate_game/main.py1
22 files changed, 448 insertions, 176 deletions
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/BluetoothAlarmDialog.qml b/examples/bluetooth/heartrate_game/HeartRateGame/BluetoothAlarmDialog.qml
index 3687b1331..16b4d32b3 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/BluetoothAlarmDialog.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/BluetoothAlarmDialog.qml
@@ -52,7 +52,7 @@ Item {
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap
- font.pixelSize: GameSettings.mediumFontSize
+ font.pixelSize: GameSettings.smallFontSize
color: GameSettings.textColor
text: root.permissionError
? qsTr("Bluetooth permissions are not granted. Please grant the permissions in the system settings.")
@@ -70,8 +70,8 @@ Item {
Text {
anchors.centerIn: parent
color: GameSettings.textColor
- font.pixelSize: GameSettings.bigFontSize
- text: qsTr("Quit")
+ font.pixelSize: GameSettings.microFontSize
+ text: qsTr("QUIT")
}
}
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/BottomLine.qml b/examples/bluetooth/heartrate_game/HeartRateGame/BottomLine.qml
index caebc307e..80fdaa8cd 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/BottomLine.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/BottomLine.qml
@@ -6,7 +6,6 @@ import QtQuick
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
- width: parent.width * 0.85
+ width: parent.width
height: parent.height * 0.05
- radius: height*0.5
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/Connect.qml b/examples/bluetooth/heartrate_game/HeartRateGame/Connect.qml
index ca8ef2923..ed5fb63d7 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/Connect.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/Connect.qml
@@ -16,43 +16,39 @@ GamePage {
errorMessage: deviceFinder.error
infoMessage: deviceFinder.info
+ iconType: deviceFinder.icon
+
+ Text {
+ id: viewCaption
+ anchors {
+ top: parent.top
+ topMargin: GameSettings.fieldMargin + connectPage.messageHeight
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width - GameSettings.fieldMargin * 2
+ height: GameSettings.fieldHeight
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ color: GameSettings.textColor
+ font.pixelSize: GameSettings.smallFontSize
+ text: qsTr("Found Devices")
+ }
Rectangle {
id: viewContainer
- anchors.top: parent.top
+ anchors.top: viewCaption.bottom
// only BlueZ platform has address type selection
anchors.bottom: connectPage.connectionHandler.requiresAddressType ? addressTypeButton.top
: searchButton.top
- anchors.topMargin: GameSettings.fieldMargin + connectPage.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
+ anchors.fill: parent
model: connectPage.deviceFinder.devices
clip: true
@@ -76,22 +72,22 @@ GamePage {
Text {
id: device
- font.pixelSize: GameSettings.smallFontSize
+ font.pixelSize: GameSettings.microFontSize
text: box.modelData.deviceName
anchors.top: parent.top
- anchors.topMargin: parent.height * 0.1
- anchors.leftMargin: parent.height * 0.1
+ anchors.topMargin: parent.height * 0.15
+ anchors.leftMargin: parent.height * 0.15
anchors.left: parent.left
color: GameSettings.textColor
}
Text {
id: deviceAddress
- font.pixelSize: GameSettings.smallFontSize
+ font.pixelSize: GameSettings.microFontSize
text: box.modelData.deviceAddress
anchors.bottom: parent.bottom
- anchors.bottomMargin: parent.height * 0.1
- anchors.rightMargin: parent.height * 0.1
+ anchors.bottomMargin: parent.height * 0.15
+ anchors.rightMargin: parent.height * 0.15
anchors.right: parent.right
color: Qt.darker(GameSettings.textColor)
}
@@ -114,19 +110,19 @@ GamePage {
State {
name: "public"
PropertyChanges {
- addressTypeText.text: qsTr("Public Address")
+ addressTypeText.text: qsTr("PUBLIC ADDRESS")
}
PropertyChanges {
- connectPage.deviceHandler.addressType: DeviceHandler.PUBLIC_ADDRESS
+ connectPage.deviceHandler.addressType: DeviceHandler.PublicAddress
}
},
State {
name: "random"
PropertyChanges {
- addressTypeText.text: qsTr("Random Address")
+ addressTypeText.text: qsTr("RANDOM ADDRESS")
}
PropertyChanges {
- connectPage.deviceHandler.addressType: DeviceHandler.RANDOM_ADDRESS
+ connectPage.deviceHandler.addressType: DeviceHandler.RandomAddress
}
}
]
@@ -134,8 +130,8 @@ GamePage {
Text {
id: addressTypeText
anchors.centerIn: parent
- font.pixelSize: GameSettings.tinyFontSize
- color: GameSettings.textColor
+ font.pixelSize: GameSettings.microFontSize
+ color: GameSettings.textDarkColor
}
}
@@ -151,9 +147,9 @@ GamePage {
Text {
anchors.centerIn: parent
- font.pixelSize: GameSettings.tinyFontSize
+ font.pixelSize: GameSettings.microFontSize
text: qsTr("START SEARCH")
- color: searchButton.enabled ? GameSettings.textColor : GameSettings.disabledTextColor
+ color: GameSettings.textDarkColor
}
}
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/GamePage.qml b/examples/bluetooth/heartrate_game/HeartRateGame/GamePage.qml
index 249f94186..2d592cfdb 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/GamePage.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/GamePage.qml
@@ -11,25 +11,65 @@ Item {
property real messageHeight: msg.height
property bool hasError: errorMessage != ""
property bool hasInfo: infoMessage != ""
+ property int iconType: BluetoothBaseClass.IconNone
+
+ function iconTypeToName(icon: int) : string {
+ switch (icon) {
+ case BluetoothBaseClass.IconNone: return ""
+ case BluetoothBaseClass.IconBluetooth: return "images/bluetooth.svg"
+ case BluetoothBaseClass.IconError: return "images/alert.svg"
+ case BluetoothBaseClass.IconProgress: return "images/progress.svg"
+ case BluetoothBaseClass.IconSearch: return "images/search.svg"
+ }
+ }
Rectangle {
id: msg
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.right: parent.right
+ anchors {
+ top: parent.top
+ left: parent.left
+ right: parent.right
+ topMargin: GameSettings.fieldMargin * 0.5
+ leftMargin: GameSettings.fieldMargin
+ rightMargin: GameSettings.fieldMargin
+ }
height: GameSettings.fieldHeight
- color: page.hasError ? GameSettings.errorColor : GameSettings.infoColor
+ radius: GameSettings.buttonRadius
+ color: page.hasError ? GameSettings.errorColor : "transparent"
visible: page.hasError || page.hasInfo
+ border {
+ width: 1
+ color: page.hasError ? GameSettings.errorColor : GameSettings.infoColor
+ }
+
+ Image {
+ id: icon
+ readonly property int imgSize: GameSettings.fieldHeight * 0.5
+ anchors {
+ left: parent.left
+ leftMargin: GameSettings.fieldMargin * 0.5
+ verticalCenter: parent.verticalCenter
+ }
+ visible: source.toString() !== ""
+ source: page.iconTypeToName(page.iconType)
+ sourceSize.width: imgSize
+ sourceSize.height: imgSize
+ fillMode: Image.PreserveAspectFit
+ }
Text {
id: error
- anchors.fill: parent
+ anchors {
+ fill: parent
+ leftMargin: GameSettings.fieldMargin + icon.width
+ rightMargin: GameSettings.fieldMargin + icon.width
+ }
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
minimumPixelSize: 5
- font.pixelSize: GameSettings.smallFontSize
+ font.pixelSize: GameSettings.microFontSize
fontSizeMode: Text.Fit
- color: GameSettings.textColor
+ color: page.hasError ? GameSettings.textColor : GameSettings.infoColor
text: page.hasError ? page.errorMessage : page.infoMessage
}
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/GameSettings.qml b/examples/bluetooth/heartrate_game/HeartRateGame/GameSettings.qml
index 0fe854609..4032787ce 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/GameSettings.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/GameSettings.qml
@@ -4,35 +4,49 @@
pragma Singleton
import QtQuick
-Item {
+QtObject {
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 lightGreenColor: "#80ebb6"
+ readonly property color backgroundColor: "#2c3038"
+ readonly property color buttonColor: "#2cde85"
+ readonly property color buttonPressedColor: lightGreenColor
+ readonly property color disabledButtonColor: "#808080"
+ readonly property color viewColor: "#262626"
+ readonly property color delegate1Color: "#262626"
+ readonly property color delegate2Color: "#404040"
readonly property color textColor: "#ffffff"
- readonly property color textDarkColor: "#232323"
- readonly property color disabledTextColor: "#777777"
- readonly property color sliderColor: "#6ccaf2"
+ readonly property color textDarkColor: "#0d0d0d"
+ readonly property color textInfoColor: lightGreenColor
+ readonly property color sliderColor: "#00414a"
+ readonly property color sliderBorderColor: lightGreenColor
+ readonly property color sliderTextColor: lightGreenColor
readonly property color errorColor: "#ba3f62"
- readonly property color infoColor: "#3fba62"
+ readonly property color infoColor: lightGreenColor
+ readonly property color titleColor: "#202227"
+ readonly property color selectedTitleColor: "#19545c"
+ readonly property color hoverTitleColor: Qt.rgba(selectedTitleColor.r,
+ selectedTitleColor.g,
+ selectedTitleColor.b,
+ 0.25)
+ readonly property color bottomLineColor: "#e6e6e6"
+ readonly property color heartRateColor: "#f80067"
+
+ // All the fonts are given for the window of certain size.
+ // Resizing the window changes all the fonts accordingly
+ readonly property int defaultSize: 500
+ readonly property real fontScaleFactor: Math.min(wWidth, wHeight) / defaultSize
// 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
+ readonly property real microFontSize: 16 * fontScaleFactor
+ readonly property real tinyFontSize: 20 * fontScaleFactor
+ readonly property real smallFontSize: 24 * fontScaleFactor
+ readonly property real mediumFontSize: 32 * fontScaleFactor
+ readonly property real bigFontSize: 36 * fontScaleFactor
+ readonly property real largeFontSize: 54 * fontScaleFactor
+ readonly property real hugeFontSize: 128 * fontScaleFactor
// Some other values
property real fieldHeight: wHeight * 0.08
@@ -41,10 +55,6 @@ Item {
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/HeartRateGame/Measure.qml b/examples/bluetooth/heartrate_game/HeartRateGame/Measure.qml
index 48e84e762..04ebeb09a 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/Measure.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/Measure.qml
@@ -11,10 +11,15 @@ GamePage {
errorMessage: deviceHandler.error
infoMessage: deviceHandler.info
+ iconType: deviceHandler.icon
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)
+
+ readonly property string relaxText: qsTr("Relax!")
+ readonly property string startText: qsTr("When you are ready,\npress Start.")
+ readonly property string instructionText: qsTr("You have %1s time to increase heart\nrate as much as possible.").arg(__maxTimeCount)
+ readonly property string goodLuckText: qsTr("Good luck!")
signal showStatsPage
@@ -55,6 +60,10 @@ GamePage {
Rectangle {
id: circle
+
+ readonly property bool hintVisible: !measurePage.deviceHandler.measuring
+ readonly property real innerSpacing: Math.min(width * 0.05, 25)
+
anchors.horizontalCenter: parent.horizontalCenter
width: Math.min(measurePage.width, measurePage.height - GameSettings.fieldHeight * 4)
- 2 * GameSettings.fieldMargin
@@ -63,30 +72,127 @@ GamePage {
color: GameSettings.viewColor
Text {
- id: hintText
- anchors.centerIn: parent
- anchors.verticalCenterOffset: -parent.height * 0.1
+ id: relaxTextBox
+ anchors {
+ bottom: startTextBox.top
+ bottomMargin: parent.innerSpacing
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width * 0.6
+ height: 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: !measurePage.deviceHandler.measuring
+ visible: circle.hintVisible
color: GameSettings.textColor
fontSizeMode: Text.Fit
- minimumPixelSize: 10
- font.pixelSize: GameSettings.mediumFontSize
+ font.pixelSize: GameSettings.smallFontSize
+ font.bold: true
}
Text {
- id: text
- anchors.centerIn: parent
- anchors.verticalCenterOffset: -parent.height * 0.15
- font.pixelSize: parent.width * 0.45
+ id: startTextBox
+ anchors {
+ bottom: heart.top
+ bottomMargin: parent.innerSpacing
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width * 0.8
+ height: parent.height * 0.15
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: measurePage.startText
+ visible: circle.hintVisible
+ color: GameSettings.textColor
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.tinyFontSize
+ }
+
+ Text {
+ id: measureTextBox
+ anchors {
+ bottom: heart.top
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width * 0.7
+ height: parent.height * 0.35
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
text: measurePage.deviceHandler.hr
visible: measurePage.deviceHandler.measuring
+ color: GameSettings.heartRateColor
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.hugeFontSize
+ font.bold: true
+ }
+
+ Image {
+ id: heart
+ anchors.centerIn: circle
+ width: parent.width * 0.2
+ height: width
+ fillMode: Image.PreserveAspectFit
+ source: "images/heart.png"
+ smooth: true
+ antialiasing: true
+
+ SequentialAnimation {
+ id: heartAnim
+ running: measurePage.deviceHandler.measuring
+ loops: Animation.Infinite
+ alwaysRunToEnd: true
+ PropertyAnimation {
+ target: heart
+ property: "scale"
+ to: 1.4
+ duration: 500
+ easing.type: Easing.InQuad
+ }
+ PropertyAnimation {
+ target: heart
+ property: "scale"
+ to: 1.0
+ duration: 500
+ easing.type: Easing.OutQuad
+ }
+ }
+ }
+
+ Text {
+ id: instructionTextBox
+ anchors {
+ top: heart.bottom
+ topMargin: parent.innerSpacing
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width * 0.8
+ height: parent.height * 0.15
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: measurePage.instructionText
+ visible: circle.hintVisible
color: GameSettings.textColor
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.tinyFontSize
+ }
+
+ Text {
+ id: goodLuckBox
+ anchors {
+ top: instructionTextBox.bottom
+ topMargin: parent.innerSpacing
+ horizontalCenter: parent.horizontalCenter
+ }
+ width: parent.width * 0.6
+ height: parent.height * 0.1
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: measurePage.goodLuckText
+ visible: circle.hintVisible
+ color: GameSettings.textColor
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.smallFontSize
+ font.bold: true
}
Item {
@@ -101,14 +207,22 @@ GamePage {
Text {
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
+ width: parent.width * 0.35
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
text: measurePage.deviceHandler.minHR
color: GameSettings.textColor
- font.pixelSize: GameSettings.hugeFontSize
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.largeFontSize
Text {
anchors.left: parent.left
anchors.bottom: parent.top
- font.pixelSize: parent.font.pixelSize * 0.8
+ horizontalAlignment: Text.AlignLeft
+ verticalAlignment: Text.AlignVCenter
+ width: parent.width
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.mediumFontSize
color: parent.color
text: "MIN"
}
@@ -117,51 +231,27 @@ GamePage {
Text {
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
+ horizontalAlignment: Text.AlignRight
+ verticalAlignment: Text.AlignVCenter
+ width: parent.width * 0.35
text: measurePage.deviceHandler.maxHR
color: GameSettings.textColor
- font.pixelSize: GameSettings.hugeFontSize
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.largeFontSize
Text {
anchors.right: parent.right
anchors.bottom: parent.top
- font.pixelSize: parent.font.pixelSize * 0.8
+ horizontalAlignment: Text.AlignRight
+ verticalAlignment: Text.AlignVCenter
+ width: parent.width
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.mediumFontSize
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: measurePage.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 {
@@ -171,21 +261,43 @@ GamePage {
width: circle.width
height: GameSettings.fieldHeight
radius: GameSettings.buttonRadius
+ border {
+ width: 1
+ color: GameSettings.sliderBorderColor
+ }
Rectangle {
- height: parent.height
+ anchors {
+ top: parent.top
+ topMargin: parent.border.width
+ left: parent.left
+ leftMargin: parent.border.width
+ }
+ height: parent.height - 2 * parent.border.width
+ width: Math.min(1.0, measurePage.__timeCounter / measurePage.__maxTimeCount)
+ * (parent.width - 2 * parent.border.width)
radius: parent.radius
color: GameSettings.sliderColor
- width: Math.min(
- 1.0,
- measurePage.__timeCounter / measurePage.__maxTimeCount) * parent.width
+ }
+
+ Image {
+ readonly property int imgSize: GameSettings.fieldHeight * 0.5
+ anchors {
+ verticalCenter: parent.verticalCenter
+ left: parent.left
+ leftMargin: GameSettings.fieldMargin * 0.5
+ }
+ source: "images/clock.svg"
+ sourceSize.width: imgSize
+ sourceSize.height: imgSize
+ fillMode: Image.PreserveAspectFit
}
Text {
anchors.centerIn: parent
- color: "gray"
+ color: GameSettings.sliderTextColor
text: (measurePage.__maxTimeCount - measurePage.__timeCounter).toFixed(0) + " s"
- font.pixelSize: GameSettings.bigFontSize
+ font.pixelSize: GameSettings.smallFontSize
}
}
}
@@ -197,16 +309,17 @@ GamePage {
anchors.bottomMargin: GameSettings.fieldMargin
width: circle.width
height: GameSettings.fieldHeight
- enabled: !measurePage.deviceHandler.measuring
+ enabled: measurePage.deviceHandler.alive && !measurePage.deviceHandler.measuring
+ && measurePage.errorMessage === ""
radius: GameSettings.buttonRadius
onClicked: measurePage.start()
Text {
anchors.centerIn: parent
- font.pixelSize: GameSettings.tinyFontSize
+ font.pixelSize: GameSettings.microFontSize
text: qsTr("START")
- color: startButton.enabled ? GameSettings.textColor : GameSettings.disabledTextColor
+ color: GameSettings.textDarkColor
}
}
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/SplashScreen.qml b/examples/bluetooth/heartrate_game/HeartRateGame/SplashScreen.qml
index 2f9ac1b3f..918319d78 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/SplashScreen.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/SplashScreen.qml
@@ -23,7 +23,7 @@ Item {
Timer {
id: splashTimer
interval: 1000
- onTriggered: splashIsReady = true
+ onTriggered: root.splashIsReady = true
}
Component.onCompleted: splashTimer.start()
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/Stats.qml b/examples/bluetooth/heartrate_game/HeartRateGame/Stats.qml
index 22cdd5365..87487c944 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/Stats.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/Stats.qml
@@ -13,20 +13,45 @@ GamePage {
anchors.centerIn: parent
width: parent.width
- Text {
+ Rectangle {
+ id: resultRect
anchors.horizontalCenter: parent.horizontalCenter
- font.pixelSize: GameSettings.hugeFontSize
- color: GameSettings.textColor
- text: qsTr("RESULT")
- }
+ width: height
+ height: statsPage.height / 2 - GameSettings.fieldHeight
+ radius: height / 2
+ color: GameSettings.viewColor
- Text {
- anchors.horizontalCenter: parent.horizontalCenter
- font.pixelSize: GameSettings.giganticFontSize * 3
- color: GameSettings.textColor
- text: (statsPage.deviceHandler.maxHR - statsPage.deviceHandler.minHR).toFixed(0)
+ Column {
+ anchors.centerIn: parent
+
+ Text {
+ id: resultCaption
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: resultRect.width * 0.8
+ height: resultRect.height * 0.15
+ horizontalAlignment: Text.AlignHCenter
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.bigFontSize
+ color: GameSettings.textColor
+ text: qsTr("RESULT")
+ }
+
+ Text {
+ id: resultValue
+ anchors.horizontalCenter: parent.horizontalCenter
+ width: resultRect.width * 0.8
+ height: resultRect.height * 0.4
+ horizontalAlignment: Text.AlignHCenter
+ fontSizeMode: Text.Fit
+ font.pixelSize: GameSettings.hugeFontSize
+ font.bold: true
+ color: GameSettings.heartRateColor
+ text: (statsPage.deviceHandler.maxHR - statsPage.deviceHandler.minHR).toFixed(0)
+ }
+ }
}
+
Item {
height: GameSettings.fieldHeight
width: 1
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/TitleBar.qml b/examples/bluetooth/heartrate_game/HeartRateGame/TitleBar.qml
index 016a44358..ccec76089 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/TitleBar.qml
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/TitleBar.qml
@@ -13,42 +13,51 @@ Rectangle {
signal titleClicked(int index)
height: GameSettings.fieldHeight
- color: GameSettings.viewColor
+ color: GameSettings.titleColor
+
+ Rectangle {
+ anchors.bottom: parent.bottom
+ width: parent.width / 3
+ height: parent.height
+ x: titleBar.currentIndex * width
+ color: GameSettings.selectedTitleColor
+
+ BottomLine {
+ color: GameSettings.bottomLineColor
+ }
+
+ Behavior on x {
+ NumberAnimation {
+ duration: 200
+ }
+ }
+ }
Repeater {
model: 3
- Text {
+ Rectangle {
id: caption
required property int index
+ property bool hoveredOrPressed: mouseArea.pressed || mouseArea.containsMouse
width: titleBar.width / 3
height: titleBar.height
x: index * width
- horizontalAlignment: Text.AlignHCenter
- verticalAlignment: Text.AlignVCenter
- text: titleBar.__titles[index]
- font.pixelSize: GameSettings.tinyFontSize
- color: titleBar.currentIndex === index ? GameSettings.textColor
- : GameSettings.disabledTextColor
-
+ color: (titleBar.currentIndex !== index) && hoveredOrPressed
+ ? GameSettings.hoverTitleColor : "transparent"
+ Text {
+ anchors.fill: parent
+ horizontalAlignment: Text.AlignHCenter
+ verticalAlignment: Text.AlignVCenter
+ text: titleBar.__titles[caption.index]
+ font.pixelSize: GameSettings.microFontSize
+ color: GameSettings.textColor
+ }
MouseArea {
+ id: mouseArea
anchors.fill: parent
+ hoverEnabled: true
onClicked: titleBar.titleClicked(caption.index)
}
}
}
-
- Item {
- anchors.bottom: parent.bottom
- width: parent.width / 3
- height: parent.height
- x: titleBar.currentIndex * width
-
- BottomLine {}
-
- Behavior on x {
- NumberAnimation {
- duration: 200
- }
- }
- }
}
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/alert.svg b/examples/bluetooth/heartrate_game/HeartRateGame/images/alert.svg
new file mode 100644
index 000000000..c48c10e6b
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/alert.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 4C16.4183 4 20 7.58172 20 12C20 16.4183 16.4183 20 12 20C7.58172 20 4 16.4183 4 12C4 7.58172 7.58172 4 12 4ZM12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2Z" fill="white"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 13C11.4477 13 11 12.5523 11 12V8C11 7.44772 11.4477 7 12 7C12.5523 7 13 7.44772 13 8V12C13 12.5523 12.5523 13 12 13ZM12 15C12.5523 15 13 15.4477 13 16C13 16.5523 12.5523 17 12 17C11.4477 17 11 16.5523 11 16C11 15.4477 11.4477 15 12 15Z" fill="white"/>
+</svg>
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/bluetooth.svg b/examples/bluetooth/heartrate_game/HeartRateGame/images/bluetooth.svg
new file mode 100644
index 000000000..6d01b28ff
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/bluetooth.svg
@@ -0,0 +1,3 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M11.1869 2.24413C11.4926 2.11749 11.8445 2.18749 12.0785 2.42149L16.5785 6.92149C16.8981 7.24101 16.8981 7.75905 16.5785 8.07857L12.6571 12L16.5785 15.9215C16.8981 16.241 16.8981 16.7591 16.5785 17.0786L12.0785 21.5786C11.8445 21.8126 11.4926 21.8826 11.1869 21.7559C10.8812 21.6293 10.6818 21.331 10.6818 21V13.9753L7.57855 17.0786C7.25903 17.3981 6.74098 17.3981 6.42146 17.0786C6.10194 16.7591 6.10194 16.241 6.42146 15.9215L10.3429 12L6.42146 8.07857C6.10194 7.75905 6.10194 7.24101 6.42146 6.92149C6.74098 6.60197 7.25903 6.60197 7.57855 6.92149L10.6818 10.0248V3.00003C10.6818 2.66911 10.8812 2.37077 11.1869 2.24413ZM12.3182 13.9753L14.8429 16.5L12.3182 19.0248V13.9753ZM12.3182 10.0248V4.9753L14.8429 7.50003L12.3182 10.0248Z" fill="#80EBB6"/>
+</svg>
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/clock.svg b/examples/bluetooth/heartrate_game/HeartRateGame/images/clock.svg
new file mode 100644
index 000000000..655996bab
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/clock.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M8 20H16V17C16 15.9 15.6083 14.9583 14.825 14.175C14.0417 13.3917 13.1 13 12 13C10.9 13 9.95833 13.3917 9.175 14.175C8.39167 14.9583 8 15.9 8 17V20ZM12 11C13.1 11 14.0417 10.6083 14.825 9.825C15.6083 9.04167 16 8.1 16 7V4H8V7C8 8.1 8.39167 9.04167 9.175 9.825C9.95833 10.6083 10.9 11 12 11ZM5 22C4.44772 22 4 21.5523 4 21C4 20.4477 4.44772 20 5 20H6V17C6 15.9833 6.2375 15.0292 6.7125 14.1375C7.1875 13.2458 7.85 12.5333 8.7 12C7.85 11.4667 7.1875 10.7542 6.7125 9.8625C6.2375 8.97083 6 8.01667 6 7V4H5C4.44772 4 4 3.55228 4 3C4 2.44772 4.44772 2 5 2H19C19.5523 2 20 2.44772 20 3C20 3.55228 19.5523 4 19 4H18V7C18 8.01667 17.7625 8.97083 17.2875 9.8625C16.8125 10.7542 16.15 11.4667 15.3 12C16.15 12.5333 16.8125 13.2458 17.2875 14.1375C17.7625 15.0292 18 15.9833 18 17V20H19C19.5523 20 20 20.4477 20 21C20 21.5523 19.5523 22 19 22H5Z" fill="#80EBB6"/>
+<path d="M17 22H7L7 18C7 15.2386 9.23858 13 12 13C14.7614 13 17 15.2386 17 18V22Z" fill="#80EBB6"/>
+</svg>
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/heart.png b/examples/bluetooth/heartrate_game/HeartRateGame/images/heart.png
index f2b3c0a3e..4ba0f822d 100644
--- a/examples/bluetooth/heartrate_game/HeartRateGame/images/heart.png
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/heart.png
Binary files differ
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/progress.svg b/examples/bluetooth/heartrate_game/HeartRateGame/images/progress.svg
new file mode 100644
index 000000000..449fe5e73
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/progress.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M19 11C19 11.5523 19.4477 12 20 12C20.5523 12 21 11.5523 21 11V10.8478C21 8.11075 19.7088 5.53404 17.5163 3.89561C17.0739 3.56501 16.4472 3.65565 16.1166 4.09805C15.786 4.54046 15.8767 5.1671 16.3191 5.4977C18.0064 6.75857 19 8.74149 19 10.8478V11ZM4 12C4.55228 12 5 11.5523 5 11V10.8478C5 8.74149 5.99363 6.75857 7.68091 5.4977C8.12331 5.1671 8.21395 4.54046 7.88335 4.09805C7.55275 3.65565 6.92611 3.56501 6.4837 3.89561C4.29117 5.53404 3 8.11075 3 10.8478V11C3 11.5523 3.44772 12 4 12ZM7.10555 19.5528C7.35253 19.0588 7.95321 18.8586 8.44719 19.1055C10.6837 20.2238 13.3162 20.2238 15.5528 19.1056C16.0467 18.8586 16.6474 19.0588 16.8944 19.5528C17.1414 20.0468 16.9412 20.6474 16.4472 20.8944C13.6476 22.2942 10.3523 22.2942 7.55276 20.8944C7.05878 20.6474 6.85856 20.0467 7.10555 19.5528Z" fill="#80EBB6"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M13 5C13 5.55228 12.5523 6 12 6C11.4477 6 11 5.55228 11 5C11 4.44772 11.4477 4 12 4C12.5523 4 13 4.44772 13 5ZM15 5C15 6.65685 13.6569 8 12 8C10.3431 8 9 6.65685 9 5C9 3.34315 10.3431 2 12 2C13.6569 2 15 3.34315 15 5ZM5 17C5.55228 17 6 16.5523 6 16C6 15.4477 5.55228 15 5 15C4.44772 15 4 15.4477 4 16C4 16.5523 4.44772 17 5 17ZM5 19C6.65685 19 8 17.6569 8 16C8 14.3431 6.65685 13 5 13C3.34315 13 2 14.3431 2 16C2 17.6569 3.34315 19 5 19ZM19 17C19.5523 17 20 16.5523 20 16C20 15.4477 19.5523 15 19 15C18.4477 15 18 15.4477 18 16C18 16.5523 18.4477 17 19 17ZM19 19C20.6569 19 22 17.6569 22 16C22 14.3431 20.6569 13 19 13C17.3431 13 16 14.3431 16 16C16 17.6569 17.3431 19 19 19Z" fill="#80EBB6"/>
+</svg>
diff --git a/examples/bluetooth/heartrate_game/HeartRateGame/images/search.svg b/examples/bluetooth/heartrate_game/HeartRateGame/images/search.svg
new file mode 100644
index 000000000..9af5fe4d7
--- /dev/null
+++ b/examples/bluetooth/heartrate_game/HeartRateGame/images/search.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M14.2929 14.2929C14.6834 13.9024 15.3166 13.9024 15.7071 14.2929L21.7071 20.2929C22.0976 20.6834 22.0976 21.3166 21.7071 21.7071C21.3166 22.0976 20.6834 22.0976 20.2929 21.7071L14.2929 15.7071C13.9024 15.3166 13.9024 14.6834 14.2929 14.2929Z" fill="#80EBB6"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M10 4C6.68629 4 4 6.68629 4 10C4 13.3137 6.68629 16 10 16C13.3137 16 16 13.3137 16 10C16 6.68629 13.3137 4 10 4ZM2 10C2 5.58172 5.58172 2 10 2C14.4183 2 18 5.58172 18 10C18 14.4183 14.4183 18 10 18C5.58172 18 2 14.4183 2 10Z" fill="#80EBB6"/>
+</svg>
diff --git a/examples/bluetooth/heartrate_game/bluetoothbaseclass.py b/examples/bluetooth/heartrate_game/bluetoothbaseclass.py
index 6278b0418..7f4c5a5b4 100644
--- a/examples/bluetooth/heartrate_game/bluetoothbaseclass.py
+++ b/examples/bluetooth/heartrate_game/bluetoothbaseclass.py
@@ -2,18 +2,36 @@
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
from __future__ import annotations
-from PySide6.QtCore import QObject, Property, Signal, Slot
+from enum import IntEnum
+from PySide6.QtQml import QmlElement, QmlUncreatable
+from PySide6.QtCore import QObject, Property, Signal, Slot, QEnum
+QML_IMPORT_NAME = "HeartRateGame"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@QmlElement
+@QmlUncreatable("BluetoothBaseClass is not intended to be created directly")
class BluetoothBaseClass(QObject):
+ @QEnum
+ class IconType(IntEnum):
+ IconNone = 0
+ IconBluetooth = 1
+ IconError = 2
+ IconProgress = 3
+ IconSearch = 4
+
errorChanged = Signal()
infoChanged = Signal()
+ iconChanged = Signal()
def __init__(self, parent=None):
super().__init__(parent)
self.m_error = ""
self.m_info = ""
+ self.m_icon = BluetoothBaseClass.IconType.IconNone
@Property(str, notify=errorChanged)
def error(self):
@@ -35,7 +53,18 @@ class BluetoothBaseClass(QObject):
self.m_info = i
self.infoChanged.emit()
+ @Property(int, notify=iconChanged)
+ def icon(self):
+ return self.m_icon
+
+ @icon.setter
+ def icon(self, i):
+ if self.m_icon != i:
+ self.m_icon = i
+ self.iconChanged.emit()
+
@Slot()
def clearMessages(self):
self.info = ""
self.error = ""
+ self.icon = BluetoothBaseClass.IconType.IconNone
diff --git a/examples/bluetooth/heartrate_game/devicefinder.py b/examples/bluetooth/heartrate_game/devicefinder.py
index 5c00e7c94..932f2bb4c 100644
--- a/examples/bluetooth/heartrate_game/devicefinder.py
+++ b/examples/bluetooth/heartrate_game/devicefinder.py
@@ -5,7 +5,7 @@ import sys
from PySide6.QtBluetooth import (QBluetoothDeviceDiscoveryAgent,
QBluetoothDeviceInfo)
-from PySide6.QtQml import QmlElement
+from PySide6.QtQml import QmlElement, QmlUncreatable
from PySide6.QtCore import QTimer, Property, Signal, Slot, Qt
from bluetoothbaseclass import BluetoothBaseClass
@@ -22,6 +22,7 @@ QML_IMPORT_MAJOR_VERSION = 1
@QmlElement
+@QmlUncreatable("This class is not intended to be created directly")
class DeviceFinder(BluetoothBaseClass):
scanningChanged = Signal()
@@ -57,6 +58,7 @@ class DeviceFinder(BluetoothBaseClass):
qApp.requestPermission(permission, self, self.startSearch) # noqa: F82 1
return
elif permission_status == Qt.PermissionStatus.Denied:
+ self.icon = BluetoothBaseClass.IconType.IconError
return
elif permission_status == Qt.PermissionStatus.Granted:
print("[HeartRateGame] Bluetooth Permission Granted")
@@ -75,6 +77,7 @@ class DeviceFinder(BluetoothBaseClass):
#! [devicediscovery-2]
self.scanningChanged.emit()
self.info = "Scanning for devices..."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
#! [devicediscovery-3]
@Slot(QBluetoothDeviceInfo)
@@ -83,6 +86,7 @@ class DeviceFinder(BluetoothBaseClass):
if device.coreConfigurations() & QBluetoothDeviceInfo.LowEnergyCoreConfiguration:
self.m_devices.append(DeviceInfo(device))
self.info = "Low Energy device found. Scanning more..."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
#! [devicediscovery-3]
self.devicesChanged.emit()
#! [devicediscovery-4]
@@ -97,6 +101,7 @@ class DeviceFinder(BluetoothBaseClass):
self.error = "Writing or reading from the device resulted in an error."
else:
self.error = "An unknown error has occurred."
+ self.icon = BluetoothBaseClass.IconType.IconError
@Slot()
def scanFinished(self):
@@ -107,12 +112,20 @@ class DeviceFinder(BluetoothBaseClass):
if self.m_devices:
self.info = "Scanning done."
+ self.icon = BluetoothBaseClass.IconType.IconBluetooth
else:
self.error = "No Low Energy devices found."
+ self.icon = BluetoothBaseClass.IconType.IconError
self.scanningChanged.emit()
self.devicesChanged.emit()
+ @Slot()
+ def resetMessages(self):
+ self.error = ""
+ self.info = "Start search to find devices"
+ self.icon = BluetoothBaseClass.IconType.IconSearch
+
@Slot(str)
def connectToService(self, address):
self.m_deviceDiscoveryAgent.stop()
@@ -127,7 +140,7 @@ class DeviceFinder(BluetoothBaseClass):
if currentDevice:
self.m_deviceHandler.setDevice(currentDevice)
- self.clearMessages()
+ self.resetMessages()
@Property(bool, notify=scanningChanged)
def scanning(self):
diff --git a/examples/bluetooth/heartrate_game/devicehandler.py b/examples/bluetooth/heartrate_game/devicehandler.py
index 8599c0296..f10c052be 100644
--- a/examples/bluetooth/heartrate_game/devicehandler.py
+++ b/examples/bluetooth/heartrate_game/devicehandler.py
@@ -69,31 +69,37 @@ class DeviceHandler(BluetoothBaseClass):
self.m_demoTimer.start()
self.updateDemoHR()
- @Property(int)
def addressType(self):
if self.m_addressType == QLowEnergyController.RemoteAddressType.RandomAddress:
return DeviceHandler.AddressType.RANDOM_ADDRESS
return DeviceHandler.AddressType.PUBLIC_ADDRESS
- @addressType.setter
- def addressType(self, type):
+ @Slot(int)
+ def setAddressType(self, type):
if type == DeviceHandler.AddressType.PUBLIC_ADDRESS:
self.m_addressType = QLowEnergyController.RemoteAddressType.PublicAddress
elif type == DeviceHandler.AddressType.RANDOM_ADDRESS:
self.m_addressType = QLowEnergyController.RemoteAddressType.RandomAddress
+ @Slot()
+ def resetAddressType(self):
+ self.m_addressType = QLowEnergyController.RemoteAddressType.PublicAddress
+
@Slot(QLowEnergyController.Error)
def controllerErrorOccurred(self, device):
self.error = "Cannot connect to remote device."
+ self.icon = BluetoothBaseClass.IconType.IconError
@Slot()
def controllerConnected(self):
self.info = "Controller connected. Search services..."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
self.m_control.discoverServices()
@Slot()
def controllerDisconnected(self):
self.error = "LowEnergy controller disconnected"
+ self.icon = BluetoothBaseClass.IconType.IconError
def setDevice(self, device):
self.clearMessages()
@@ -101,6 +107,7 @@ class DeviceHandler(BluetoothBaseClass):
if simulator():
self.info = "Demo device connected."
+ self.icon = BluetoothBaseClass.IconType.IconBluetooth
return
# Disconnect and delete old connection
@@ -152,6 +159,7 @@ class DeviceHandler(BluetoothBaseClass):
def serviceDiscovered(self, gatt):
if gatt == QBluetoothUuid(QBluetoothUuid.ServiceClassUuid.HeartRate):
self.info = "Heart Rate service discovered. Waiting for service scan to be done..."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
self.m_foundHeartRateService = True
#! [Filter HeartRate service 1]
@@ -159,6 +167,7 @@ class DeviceHandler(BluetoothBaseClass):
@Slot()
def serviceScanDone(self):
self.info = "Service scan done."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
# Delete old service if available
if self.m_service:
@@ -177,6 +186,8 @@ class DeviceHandler(BluetoothBaseClass):
self.m_service.discoverDetails()
else:
self.error = "Heart Rate Service not found."
+ self.icon = BluetoothBaseClass.IconType.IconError
+
#! [Filter HeartRate service 2]
# Service functions
@@ -185,8 +196,10 @@ class DeviceHandler(BluetoothBaseClass):
def serviceStateChanged(self, switch):
if switch == QLowEnergyService.RemoteServiceDiscovering:
self.info = "Discovering services..."
+ self.icon = BluetoothBaseClass.IconType.IconProgress
elif switch == QLowEnergyService.RemoteServiceDiscovered:
self.info = "Service discovered."
+ self.icon = BluetoothBaseClass.IconType.IconBluetooth
hrChar = self.m_service.characteristic(
QBluetoothUuid(QBluetoothUuid.CharacteristicType.HeartRateMeasurement))
if hrChar.isValid():
@@ -197,6 +210,7 @@ class DeviceHandler(BluetoothBaseClass):
QByteArray.fromHex(b"0100"))
else:
self.error = "HR Data not found."
+ self.icon = BluetoothBaseClass.IconType.IconError
self.aliveChanged.emit()
#! [Find HRM characteristic]
@@ -308,3 +322,5 @@ class DeviceHandler(BluetoothBaseClass):
+ (0.2017 * 24)) / 4.184) * 60 * self.time / 3600
self.statsChanged.emit()
+
+ addressType = Property(int, addressType, setAddressType, freset=resetAddressType)
diff --git a/examples/bluetooth/heartrate_game/deviceinfo.py b/examples/bluetooth/heartrate_game/deviceinfo.py
index 136bbbacb..60cdb5aaf 100644
--- a/examples/bluetooth/heartrate_game/deviceinfo.py
+++ b/examples/bluetooth/heartrate_game/deviceinfo.py
@@ -27,7 +27,7 @@ class DeviceInfo(QObject):
@Property(str, notify=deviceChanged)
def deviceName(self):
if simulator():
- return "Demo device"
+ return "Demo BT device"
return self.m_device.name()
@Property(str, notify=deviceChanged)
diff --git a/examples/bluetooth/heartrate_game/doc/heartrate_game.rst b/examples/bluetooth/heartrate_game/doc/heartrate_game.rst
index 9d190d991..1704e32d8 100644
--- a/examples/bluetooth/heartrate_game/doc/heartrate_game.rst
+++ b/examples/bluetooth/heartrate_game/doc/heartrate_game.rst
@@ -9,3 +9,6 @@ application covers the scanning for Bluetooth Low Energy devices,
connecting to a Heart Rate service on the device, writing
characteristics and descriptors, and receiving updates from the device
once the heart rate has changed.
+
+The command line option `--simulator` can be used to run the example against a
+demo server in case no Bluetooth hardware is available.
diff --git a/examples/bluetooth/heartrate_game/heartrate_global.py b/examples/bluetooth/heartrate_game/heartrate_global.py
index 384eb93a7..75a0b42b8 100644
--- a/examples/bluetooth/heartrate_game/heartrate_global.py
+++ b/examples/bluetooth/heartrate_game/heartrate_global.py
@@ -8,7 +8,6 @@ _simulator = False
def simulator():
- global _simulator
return _simulator
diff --git a/examples/bluetooth/heartrate_game/main.py b/examples/bluetooth/heartrate_game/main.py
index 00df7de6a..a70b9f349 100644
--- a/examples/bluetooth/heartrate_game/main.py
+++ b/examples/bluetooth/heartrate_game/main.py
@@ -15,6 +15,7 @@ from PySide6.QtCore import QCoreApplication, QLoggingCategory
from connectionhandler import ConnectionHandler
from devicefinder import DeviceFinder
from devicehandler import DeviceHandler
+from bluetoothbaseclass import BluetoothBaseClass # noqa: F401
from heartrate_global import set_simulator