1+ #include " displayapp/screens/HeartRateZone.h"
2+ #include < lvgl/lvgl.h>
3+ #include < components/heartrate/HeartRateController.h>
4+
5+ #include " displayapp/DisplayApp.h"
6+ #include " displayapp/InfiniTimeTheme.h"
7+
8+ using namespace Pinetime ::Applications::Screens;
9+
10+ HeartRateZone::HeartRateZone (Controllers::HeartRateController& heartRateController, System::SystemTask& systemTask)
11+ : heartRateController {heartRateController}, wakeLock(systemTask) {
12+ auto activity = heartRateController.Activity ();
13+ auto settings = heartRateController.hrzSettings ();
14+ uint32_t total = 0 ;
15+
16+ auto hundreths_of_hour = pdMS_TO_TICKS (10 * 60 * 60 );
17+ auto exercise_target = pdMS_TO_TICKS (settings.exerciseMsTarget );
18+ uint32_t offset = 25 * (zone_bar.size () + 2 );
19+
20+ lv_obj_t * screen = lv_scr_act ();
21+
22+ title = lv_label_create (screen, nullptr );
23+ lv_label_set_text_static (title, " BPM Breakdown" );
24+ lv_obj_align (title, screen, LV_ALIGN_IN_TOP_MID, 0 , 20 );
25+
26+ total_bar = lv_bar_create (screen, nullptr );
27+ lv_obj_set_style_local_bg_opa (total_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_OPA_0);
28+ lv_obj_set_style_local_line_color (total_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, Colors::bgAlt);
29+ lv_obj_set_style_local_border_width (total_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, 2 );
30+ lv_obj_set_style_local_radius (total_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, 0 );
31+ lv_obj_set_style_local_line_color (total_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_NAVY);
32+
33+ lv_obj_align (total_bar, screen, LV_ALIGN_IN_TOP_MID, 0 , offset - (zone_bar.size () * 25 ));
34+
35+ total_label = lv_label_create (total_bar, nullptr );
36+ lv_obj_align (total_label, total_bar, LV_ALIGN_CENTER, 0 , 0 );
37+ lv_obj_set_style_local_text_color (total_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_CYAN);
38+
39+ for (uint8_t i = 0 ; i < zone_bar.size (); i++) {
40+ zone_bar[i] = lv_bar_create (screen, nullptr );
41+
42+ total += activity.zoneTime [i];
43+
44+ lv_obj_set_style_local_bg_opa (zone_bar[i], LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_OPA_0);
45+ lv_obj_set_style_local_line_color (zone_bar[i], LV_BAR_PART_BG, LV_STATE_DEFAULT, Colors::bgAlt);
46+ lv_obj_set_style_local_border_width (zone_bar[i], LV_BAR_PART_BG, LV_STATE_DEFAULT, 2 );
47+ lv_obj_set_style_local_radius (zone_bar[i], LV_BAR_PART_BG, LV_STATE_DEFAULT, 0 );
48+
49+ lv_obj_set_size (zone_bar[i], 240 , 20 );
50+ lv_obj_align (zone_bar[i], screen, LV_ALIGN_IN_TOP_MID, 0 , offset - i * 25 );
51+
52+ label_time[i] = lv_label_create (zone_bar[i], nullptr );
53+ lv_obj_align (label_time[i], zone_bar[i], LV_ALIGN_CENTER, 0 , 0 );
54+
55+ lv_obj_set_style_local_text_color (label_time[i], LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_CYAN);
56+ }
57+
58+ lv_label_set_text_static (label_time[0 ], " Warm Up" );
59+ lv_label_set_text_static (label_time[1 ], " Recovery" );
60+ lv_label_set_text_static (label_time[2 ], " Aerobic" );
61+ lv_label_set_text_static (label_time[3 ], " Threshold" );
62+ lv_label_set_text_static (label_time[4 ], " Anaerobic" );
63+ lv_label_set_text_static (total_label, " Goal" );
64+
65+ lv_obj_set_style_local_line_color (zone_bar[0 ], LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::blue);
66+ lv_obj_set_style_local_line_color (zone_bar[1 ], LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::green);
67+ lv_obj_set_style_local_line_color (zone_bar[2 ], LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::orange);
68+ lv_obj_set_style_local_line_color (zone_bar[3 ], LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::deepOrange);
69+ lv_obj_set_style_local_line_color (zone_bar[4 ], LV_BAR_PART_INDIC, LV_STATE_DEFAULT, Colors::heartRed);
70+
71+ auto bar_limit = total / hundreths_of_hour;
72+
73+ for (uint8_t i = 0 ; i < zone_bar.size (); i++) {
74+ uint32_t percent = activity.zoneTime [i] / hundreths_of_hour;
75+ lv_bar_set_range (zone_bar[i], 0 , bar_limit);
76+ lv_bar_set_value (zone_bar[i], percent, LV_ANIM_OFF);
77+ }
78+
79+ lv_bar_set_range (total_bar, 0 , exercise_target);
80+ lv_bar_set_value (total_bar, total > exercise_target ? exercise_target : total, LV_ANIM_OFF);
81+
82+ taskRefresh = lv_task_create (RefreshTaskCallback, 5000 , LV_TASK_PRIO_MID, this );
83+ }
84+
85+ HeartRateZone::~HeartRateZone () {
86+ lv_task_del (taskRefresh);
87+ lv_obj_clean (lv_scr_act ());
88+ }
89+
90+ void HeartRateZone::Refresh () {
91+ auto activity = heartRateController.Activity ();
92+ auto settings = heartRateController.hrzSettings ();
93+ uint32_t total = 0 ;
94+
95+ auto hundreths_of_hour = pdMS_TO_TICKS (10 * 60 * 60 );
96+ auto exercise_target = pdMS_TO_TICKS (settings.exerciseMsTarget );
97+
98+ for (uint8_t i = 0 ; i < zone_bar.size (); i++) {
99+ total += activity.zoneTime [i];
100+ }
101+
102+ auto bar_limit = total / hundreths_of_hour;
103+
104+ for (uint8_t i = 0 ; i < zone_bar.size (); i++) {
105+ uint32_t percent = activity.zoneTime [i] / hundreths_of_hour;
106+ lv_bar_set_range (zone_bar[i], 0 , bar_limit);
107+ lv_bar_set_value (zone_bar[i], percent, LV_ANIM_OFF);
108+ }
109+
110+ lv_bar_set_range (total_bar, 0 , exercise_target);
111+ lv_bar_set_value (total_bar, total > exercise_target ? exercise_target : total, LV_ANIM_OFF);
112+ }
0 commit comments