Skip to content

Commit 1d240a4

Browse files
committed
add heart rate measurments in the background
1 parent 85a0542 commit 1d240a4

File tree

11 files changed

+451
-77
lines changed

11 files changed

+451
-77
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ list(APPEND SOURCE_FILES
412412
displayapp/screens/settings/SettingWeatherFormat.cpp
413413
displayapp/screens/settings/SettingWakeUp.cpp
414414
displayapp/screens/settings/SettingDisplay.cpp
415+
displayapp/screens/settings/SettingHeartRate.cpp
415416
displayapp/screens/settings/SettingSteps.cpp
416417
displayapp/screens/settings/SettingSetDateTime.cpp
417418
displayapp/screens/settings/SettingSetDate.cpp

src/components/settings/Settings.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@ Settings::Settings(Pinetime::Controllers::FS& fs) : fs {fs} {
88
}
99

1010
void Settings::Init() {
11-
1211
// Load default settings from Flash
1312
LoadSettingsFromFile();
1413
}
1514

1615
void Settings::SaveSettings() {
17-
1816
// verify if is necessary to save
1917
if (settingsChanged) {
2018
SaveSettingsToFile();

src/components/settings/Settings.h

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ namespace Pinetime {
5050
int colorIndex = 0;
5151
};
5252

53+
struct HeartRateBackgroundMeasurement {
54+
bool activated = false;
55+
unsigned int intervalInSeconds = 0;
56+
};
57+
5358
Settings(Pinetime::Controllers::FS& fs);
5459

5560
Settings(const Settings&) = delete;
@@ -298,10 +303,34 @@ namespace Pinetime {
298303
return bleRadioEnabled;
299304
};
300305

306+
bool IsHeartRateBackgroundMeasurementActivated() const {
307+
return settings.heartRateBackgroundMeasurement.activated;
308+
}
309+
310+
void DeactivateHeartRateBackgroundMeasurement() {
311+
if (settings.heartRateBackgroundMeasurement.activated) {
312+
settingsChanged = true;
313+
}
314+
settings.heartRateBackgroundMeasurement.activated = false;
315+
}
316+
317+
unsigned int GetHeartRateBackgroundMeasurementInterval() const {
318+
return settings.heartRateBackgroundMeasurement.intervalInSeconds;
319+
}
320+
321+
void SetHeartRateBackgroundMeasurementInterval(unsigned int newIntervalInSeconds) {
322+
if (!settings.heartRateBackgroundMeasurement.activated ||
323+
newIntervalInSeconds != settings.heartRateBackgroundMeasurement.intervalInSeconds) {
324+
settingsChanged = true;
325+
}
326+
settings.heartRateBackgroundMeasurement.intervalInSeconds = newIntervalInSeconds;
327+
settings.heartRateBackgroundMeasurement.activated = true;
328+
}
329+
301330
private:
302331
Pinetime::Controllers::FS& fs;
303332

304-
static constexpr uint32_t settingsVersion = 0x0008;
333+
static constexpr uint32_t settingsVersion = 0x0009;
305334

306335
struct SettingsData {
307336
uint32_t version = settingsVersion;
@@ -325,6 +354,8 @@ namespace Pinetime {
325354
uint16_t shakeWakeThreshold = 150;
326355

327356
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
357+
358+
HeartRateBackgroundMeasurement heartRateBackgroundMeasurement;
328359
};
329360

330361
SettingsData settings;

src/displayapp/DisplayApp.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
#include "displayapp/screens/settings/SettingSteps.h"
4949
#include "displayapp/screens/settings/SettingSetDateTime.h"
5050
#include "displayapp/screens/settings/SettingChimes.h"
51+
#include "displayapp/screens/settings/SettingHeartRate.h"
5152
#include "displayapp/screens/settings/SettingShakeThreshold.h"
5253
#include "displayapp/screens/settings/SettingBluetooth.h"
5354

@@ -603,6 +604,9 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio
603604
case Apps::SettingWakeUp:
604605
currentScreen = std::make_unique<Screens::SettingWakeUp>(settingsController);
605606
break;
607+
case Apps::SettingHeartRate:
608+
currentScreen = std::make_unique<Screens::SettingHeartRate>(settingsController);
609+
break;
606610
case Apps::SettingDisplay:
607611
currentScreen = std::make_unique<Screens::SettingDisplay>(settingsController);
608612
break;

src/displayapp/apps/Apps.h.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace Pinetime {
3636
SettingWatchFace,
3737
SettingTimeFormat,
3838
SettingWeatherFormat,
39+
SettingHeartRate,
3940
SettingDisplay,
4041
SettingWakeUp,
4142
SettingSteps,
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#include "displayapp/screens/settings/SettingHeartRate.h"
2+
#include <lvgl/lvgl.h>
3+
#include "displayapp/screens/Styles.h"
4+
#include "displayapp/screens/Screen.h"
5+
#include "displayapp/screens/Symbols.h"
6+
#include <array>
7+
#include <algorithm>
8+
9+
using namespace Pinetime::Applications::Screens;
10+
11+
namespace {
12+
void event_handler(lv_obj_t* obj, lv_event_t event) {
13+
auto* screen = static_cast<SettingHeartRate*>(obj->user_data);
14+
screen->UpdateSelected(obj, event);
15+
}
16+
}
17+
18+
constexpr std::array<Option, 8> SettingHeartRate::options;
19+
20+
SettingHeartRate::SettingHeartRate(Pinetime::Controllers::Settings& settingsController) : settingsController {settingsController} {
21+
22+
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr);
23+
24+
lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
25+
lv_obj_set_style_local_pad_all(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5);
26+
lv_obj_set_style_local_pad_inner(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5);
27+
lv_obj_set_style_local_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
28+
29+
lv_obj_set_pos(container1, 10, 60);
30+
lv_obj_set_width(container1, LV_HOR_RES - 20);
31+
lv_obj_set_height(container1, LV_VER_RES - 50);
32+
lv_cont_set_layout(container1, LV_LAYOUT_PRETTY_TOP);
33+
34+
lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr);
35+
lv_label_set_text_static(title, "Backg. Interval");
36+
lv_label_set_text(title, "Backg. Interval");
37+
lv_label_set_align(title, LV_LABEL_ALIGN_CENTER);
38+
lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 10, 15);
39+
40+
lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr);
41+
lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);
42+
lv_label_set_text_static(icon, Symbols::heartBeat);
43+
lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
44+
lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0);
45+
46+
bool isActivated = settingsController.IsHeartRateBackgroundMeasurementActivated();
47+
unsigned int currentInterval = settingsController.GetHeartRateBackgroundMeasurementInterval();
48+
49+
for (unsigned int i = 0; i < options.size(); i++) {
50+
cbOption[i] = lv_checkbox_create(container1, nullptr);
51+
lv_checkbox_set_text(cbOption[i], options[i].name);
52+
cbOption[i]->user_data = this;
53+
lv_obj_set_event_cb(cbOption[i], event_handler);
54+
SetRadioButtonStyle(cbOption[i]);
55+
56+
if (!isActivated && options[i].intervalInSeconds == -1) {
57+
lv_checkbox_set_checked(cbOption[i], true);
58+
} else if (isActivated && options[i].intervalInSeconds == (int) currentInterval) {
59+
lv_checkbox_set_checked(cbOption[i], true);
60+
}
61+
}
62+
}
63+
64+
SettingHeartRate::~SettingHeartRate() {
65+
lv_obj_clean(lv_scr_act());
66+
settingsController.SaveSettings();
67+
}
68+
69+
void SettingHeartRate::UpdateSelected(lv_obj_t* object, lv_event_t event) {
70+
if (event == LV_EVENT_CLICKED) {
71+
for (unsigned int i = 0; i < options.size(); i++) {
72+
if (object == cbOption[i]) {
73+
lv_checkbox_set_checked(cbOption[i], true);
74+
75+
int optionInterval = options[i].intervalInSeconds;
76+
77+
if (optionInterval == -1) {
78+
settingsController.DeactivateHeartRateBackgroundMeasurement();
79+
} else {
80+
settingsController.SetHeartRateBackgroundMeasurementInterval((unsigned int) optionInterval);
81+
}
82+
} else {
83+
lv_checkbox_set_checked(cbOption[i], false);
84+
}
85+
}
86+
}
87+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <lvgl/lvgl.h>
5+
6+
#include "components/settings/Settings.h"
7+
#include "displayapp/screens/ScreenList.h"
8+
#include "displayapp/screens/Screen.h"
9+
#include "displayapp/screens/Symbols.h"
10+
#include "displayapp/screens/CheckboxList.h"
11+
12+
namespace Pinetime {
13+
14+
namespace Applications {
15+
namespace Screens {
16+
17+
struct Option {
18+
const int intervalInSeconds;
19+
const char* name;
20+
};
21+
22+
class SettingHeartRate : public Screen {
23+
public:
24+
SettingHeartRate(Pinetime::Controllers::Settings& settings);
25+
~SettingHeartRate() override;
26+
27+
void UpdateSelected(lv_obj_t* object, lv_event_t event);
28+
29+
private:
30+
Pinetime::Controllers::Settings& settingsController;
31+
32+
static constexpr std::array<Option, 8> options = {{
33+
{-1, " Off"},
34+
{0, "Cont"},
35+
{15, " 15s"},
36+
{30, " 30s"},
37+
{60, " 1m"},
38+
{5 * 60, " 5m"},
39+
{10 * 60, " 10m"},
40+
{30 * 60, " 30m"},
41+
}};
42+
43+
lv_obj_t* cbOption[options.size()];
44+
};
45+
}
46+
}
47+
}

src/displayapp/screens/settings/Settings.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,22 +38,19 @@ namespace Pinetime {
3838
{Symbols::home, "Watch face", Apps::SettingWatchFace},
3939

4040
{Symbols::shoe, "Steps", Apps::SettingSteps},
41+
{Symbols::heartBeat, "Heartrate", Apps::SettingHeartRate},
4142
{Symbols::clock, "Date & Time", Apps::SettingSetDateTime},
4243
{Symbols::cloudSunRain, "Weather", Apps::SettingWeatherFormat},
43-
{Symbols::batteryHalf, "Battery", Apps::BatteryInfo},
4444

45+
{Symbols::batteryHalf, "Battery", Apps::BatteryInfo},
4546
{Symbols::clock, "Chimes", Apps::SettingChimes},
4647
{Symbols::tachometer, "Shake Calib.", Apps::SettingShakeThreshold},
4748
{Symbols::check, "Firmware", Apps::FirmwareValidation},
48-
{Symbols::bluetooth, "Bluetooth", Apps::SettingBluetooth},
4949

50+
{Symbols::bluetooth, "Bluetooth", Apps::SettingBluetooth},
5051
{Symbols::list, "About", Apps::SysInfo},
51-
52-
// {Symbols::none, "None", Apps::None},
53-
// {Symbols::none, "None", Apps::None},
54-
// {Symbols::none, "None", Apps::None},
55-
// {Symbols::none, "None", Apps::None},
56-
52+
{Symbols::none, "None", Apps::None},
53+
{Symbols::none, "None", Apps::None},
5754
}};
5855
ScreenList<nScreens> screens;
5956
};

0 commit comments

Comments
 (0)