Skip to content

Commit 599fd01

Browse files
committed
Add heart rate zone overview screen
1 parent b651a97 commit 599fd01

4 files changed

Lines changed: 167 additions & 0 deletions

File tree

src/components/heartrate/HeartRateController.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ namespace Pinetime {
8181
return zone;
8282
}
8383

84+
HeartRateZones<uint32_t> Activity() const {
85+
return currentActivity;
86+
}
87+
8488
void SetService(Pinetime::Controllers::HeartRateService* service);
8589

8690
void AdvanceDay();

src/displayapp/InfiniTimeTheme.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace Colors {
88
static constexpr lv_color_t green = LV_COLOR_MAKE(0x0, 0xb0, 0x0);
99
static constexpr lv_color_t blue = LV_COLOR_MAKE(0x0, 0x50, 0xff);
1010
static constexpr lv_color_t lightGray = LV_COLOR_MAKE(0xb0, 0xb0, 0xb0);
11+
static constexpr lv_color_t heartRed = LV_COLOR_MAKE(0xce,0x1b,0x1b);
1112

1213
static constexpr lv_color_t bg = LV_COLOR_MAKE(0x5d, 0x69, 0x7e);
1314
static constexpr lv_color_t bgAlt = LV_COLOR_MAKE(0x38, 0x38, 0x38);
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#include "displayapp/screens/HeartRateZone.h"
2+
#include <lvgl/lvgl.h>
3+
#include <lvgl/lv_obj_style.h>
4+
#include <components/heartrate/HeartRateController.h>
5+
6+
#include "displayapp/DisplayApp.h"
7+
#include "displayapp/InfiniTimeTheme.h"
8+
9+
using namespace Pinetime::Applications::Screens;
10+
11+
namespace {
12+
const char* ToString(Pinetime::Controllers::HeartRateController::States s) {
13+
switch (s) {
14+
case Pinetime::Controllers::HeartRateController::States::NotEnoughData:
15+
return "Not enough data,\nplease wait...";
16+
case Pinetime::Controllers::HeartRateController::States::NoTouch:
17+
return "No touch detected";
18+
case Pinetime::Controllers::HeartRateController::States::Running:
19+
return "Measuring...";
20+
case Pinetime::Controllers::HeartRateController::States::Stopped:
21+
return "Stopped";
22+
}
23+
return "";
24+
}
25+
26+
void btnStartStopEventHandler(lv_obj_t* obj, lv_event_t event) {
27+
auto* screen = static_cast<HeartRate*>(obj->user_data);
28+
screen->OnStartStopEvent(event);
29+
}
30+
}
31+
32+
HeartRateZone::HeartRateZone(Controllers::HeartRateController& heartRateController, System::SystemTask& systemTask)
33+
: heartRateController {heartRateController}, wakeLock(systemTask) {
34+
bool isHrRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
35+
36+
auto activity = heartRateController.Activity();
37+
uint32_t total = 0;
38+
39+
auto hundreths_of_hour = pdMS_TO_TICKS(10*60*60);
40+
41+
lv_obj_t* screen = lv_scr_act();
42+
for (uint8_t i = 0; i < zone_bar.size(); i++) {
43+
zone_bar[i] = lv_bar_create(screen, nullptr);
44+
45+
//lv_bar_set_orientation(zone_bar[i], LV_BAR_ORIENTATION_HORIZONTAL);
46+
total += activity.zoneTime[i];
47+
lv_obj_set_style_local_line_color(zone_bar[i], LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, Colors::bgAlt);
48+
lv_obj_set_size(zone_bar[i], 240, 20);
49+
lv_obj_align(zone_bar[i], nullptr, LV_ALIGN_IN_TOP_LEFT, 10, 25 * i);
50+
51+
label_time[i] = lv_label_create(zone_bar[i]);
52+
lv_obj_align(zone_bar[i], nullptr, LV_ALIGN_CENTER, 0, 0);
53+
}
54+
55+
lv_label_set_text_static(label_time[0], "Warm Up");
56+
lv_label_set_text_static(label_time[1], "Recovery");
57+
lv_label_set_text_static(label_time[2], "Aerobic");
58+
lv_label_set_text_static(label_time[3], "Threshold");
59+
lv_label_set_text_static(label_time[4], "Anaerobic");
60+
61+
lv_obj_set_style_local_line_color(zone_bar[0], LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::blue);
62+
lv_obj_set_style_local_line_color(zone_bar[1], LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::green);
63+
lv_obj_set_style_local_line_color(zone_bar[2], LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::orange);
64+
lv_obj_set_style_local_line_color(zone_bar[3], LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::deepOrange);
65+
lv_obj_set_style_local_line_color(zone_bar[4], LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::heartRed);
66+
67+
auto bar_limit = total / hundreths_of_hour;
68+
69+
for (uint8_t i = 0; i < zone_bar.size(); i++) {
70+
uint32_t percent = activity.zoneTime[i] / hundreths_of_hour;
71+
lv_bar_set_range(zone_bar[i], 0, bar_limit);
72+
lv_bar_set_value(zone_bar[i], percent, LV_ANIM_OFF);
73+
}
74+
75+
taskRefresh = lv_task_create(RefreshTaskCallback, 5000, LV_TASK_PRIO_MID, this);
76+
}
77+
78+
HeartRateZone::~HeartRateZone() {
79+
lv_task_del(taskRefresh);
80+
lv_obj_clean(lv_scr_act());
81+
}
82+
83+
void HeartRateZone::Refresh() {
84+
auto activity = heartRateController.Activity();
85+
uint32_t total = 0;
86+
87+
auto hundreths_of_hour = pdMS_TO_TICKS(10 * 60 * 60);
88+
89+
for (uint8_t i = 0; i < zone_bar.size(); i++) {
90+
total += activity.zoneTime[i];
91+
}
92+
93+
auto bar_limit = total / hundreths_of_hour;
94+
95+
for (uint8_t i = 0; i < zone_bar.size(); i++) {
96+
uint32_t percent = activity.zoneTime[i] / hundreths_of_hour;
97+
lv_bar_set_range(zone_bar[i], 0, bar_limit);
98+
lv_bar_set_value(zone_bar[i], percent, LV_ANIM_OFF);
99+
}
100+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#pragma once
2+
3+
#include <cstdint>
4+
#include <chrono>
5+
#include <array>
6+
#include "displayapp/screens/Screen.h"
7+
#include "systemtask/SystemTask.h"
8+
#include "systemtask/WakeLock.h"
9+
#include "Symbols.h"
10+
#include <lvgl/src/lv_core/lv_style.h>
11+
#include <lvgl/src/lv_core/lv_obj.h>
12+
13+
namespace Pinetime {
14+
namespace Controllers {
15+
class HeartRateController;
16+
}
17+
18+
namespace Applications {
19+
namespace Screens {
20+
21+
class HeartRateZone : public Screen {
22+
public:
23+
HeartRateZone(Controllers::HeartRateController& HeartRateController, System::SystemTask& systemTask);
24+
~HeartRateZone() override;
25+
26+
void Refresh() override;
27+
28+
void OnStartStopEvent(lv_event_t event);
29+
30+
private:
31+
Controllers::HeartRateController& heartRateController;
32+
Pinetime::System::WakeLock wakeLock;
33+
void UpdateStartStopButton(bool isRunning);
34+
35+
std::array<lv_obj_t*,5> zone_bar;
36+
std::array<lv_obj_t*,5> label_time;
37+
/*
38+
lv_obj_t* label_hr;
39+
lv_obj_t* label_bpm;
40+
lv_obj_t* label_status;
41+
lv_obj_t* btn_startStop;
42+
lv_obj_t* label_startStop;
43+
*/
44+
lv_task_t* taskRefresh;
45+
};
46+
}
47+
48+
template <>
49+
struct AppTraits<Apps::HeartRateZone> {
50+
static constexpr Apps app = Apps::HeartRateZone;
51+
static constexpr const char* icon = Screens::Symbols::heartBeat;
52+
53+
static Screens::Screen* Create(AppControllers& controllers) {
54+
return new Screens::HeartRateZone(controllers.heartRateController, *controllers.systemTask);
55+
};
56+
57+
static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) {
58+
return true;
59+
};
60+
};
61+
}
62+
}

0 commit comments

Comments
 (0)