diff options
| author | Michele Bini <michele.bini@gmail.com> | 2022-03-30 20:50:42 (GMT) |
|---|---|---|
| committer | Michele Bini <michele.bini@gmail.com> | 2022-03-31 00:12:29 (GMT) |
| commit | 12e938959eb1e2146fdec3fee7b9a304aa6889d2 (patch) | |
| tree | f57f54615ad00327e8dc33c958ec67773c49f655 /src/displayapp/screens | |
| parent | ff68f91be9cce2fb27d3b3aea9ab26fa224ea0eb (diff) | |
with heart
Diffstat (limited to 'src/displayapp/screens')
| -rw-r--r-- | src/displayapp/screens/ApplicationList.cpp | 1 | ||||
| -rw-r--r-- | src/displayapp/screens/Clock.cpp | 3 | ||||
| -rw-r--r-- | src/displayapp/screens/Clock.h | 3 | ||||
| -rw-r--r-- | src/displayapp/screens/HeartRate.cpp | 115 | ||||
| -rw-r--r-- | src/displayapp/screens/HeartRate.h | 40 | ||||
| -rw-r--r-- | src/displayapp/screens/WatchFaceDigital.cpp | 27 | ||||
| -rw-r--r-- | src/displayapp/screens/WatchFaceDigital.h | 7 |
7 files changed, 196 insertions, 0 deletions
diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index b7c8ebd..c8d608a 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -37,6 +37,7 @@ bool ApplicationList::OnTouchEvent(Pinetime::Applications::TouchEvents event) { std::unique_ptr<Screen> ApplicationList::CreateScreen1() { std::array<Screens::Tile::Applications, 6> applications {{ {Symbols::clock}, + {Symbols::heartBeat, Apps::HeartRate}, }}; return std::make_unique<Screens::Tile>(0, 1, app, settingsController, batteryController, dateTimeController, applications); diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index ab4cafd..1893856 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -19,6 +19,7 @@ Clock::Clock(DisplayApp* app, Controllers::Ble& bleController, Controllers::NotificationManager& notificatioManager, Controllers::Settings& settingsController, + Controllers::HeartRateController& heartRateController, Controllers::MotionController& motionController, System::SystemTask& systemTask) : Screen(app), @@ -28,6 +29,7 @@ Clock::Clock(DisplayApp* app, bleController {bleController}, notificatioManager {notificatioManager}, settingsController {settingsController}, + heartRateController {heartRateController}, motionController {motionController}, screen {[this, &settingsController]() { switch (settingsController.GetClockFace()) { @@ -59,6 +61,7 @@ std::unique_ptr<Screen> Clock::WatchFaceDigitalScreen() { bleController, notificatioManager, settingsController, + heartRateController, motionController, systemTask); } diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h index 5001dce..86793e9 100644 --- a/src/displayapp/screens/Clock.h +++ b/src/displayapp/screens/Clock.h @@ -4,6 +4,7 @@ #include <chrono> #include <cstdint> #include <memory> +#include <components/heartrate/HeartRateController.h> #include "displayapp/screens/Screen.h" #include "components/datetime/DateTimeController.h" #include "systemtask/SystemTask.h" @@ -27,6 +28,7 @@ namespace Pinetime { Controllers::Ble& bleController, Controllers::NotificationManager& notificatioManager, Controllers::Settings& settingsController, + Controllers::HeartRateController& heartRateController, Controllers::MotionController& motionController, System::SystemTask& systemTask); ~Clock() override; @@ -41,6 +43,7 @@ namespace Pinetime { Controllers::Ble& bleController; Controllers::NotificationManager& notificatioManager; Controllers::Settings& settingsController; + Controllers::HeartRateController& heartRateController; Controllers::MotionController& motionController; std::unique_ptr<Screen> screen; diff --git a/src/displayapp/screens/HeartRate.cpp b/src/displayapp/screens/HeartRate.cpp new file mode 100644 index 0000000..6f9154b --- /dev/null +++ b/src/displayapp/screens/HeartRate.cpp @@ -0,0 +1,115 @@ +#include "displayapp/screens/HeartRate.h" +#include <lvgl/lvgl.h> +#include <components/heartrate/HeartRateController.h> + +#include "displayapp/DisplayApp.h" + +using namespace Pinetime::Applications::Screens; + +namespace { + const char* ToString(Pinetime::Controllers::HeartRateController::States s) { + switch (s) { + case Pinetime::Controllers::HeartRateController::States::NotEnoughData: + return "Not enough data,\nplease wait..."; + case Pinetime::Controllers::HeartRateController::States::NoTouch: + return "No touch detected"; + case Pinetime::Controllers::HeartRateController::States::Running: + return "Measuring..."; + case Pinetime::Controllers::HeartRateController::States::Stopped: + return "Stopped"; + } + return ""; + } + + static void btnStartStopEventHandler(lv_obj_t* obj, lv_event_t event) { + HeartRate* screen = static_cast<HeartRate*>(obj->user_data); + screen->OnStartStopEvent(event); + } +} + +HeartRate::HeartRate(Pinetime::Applications::DisplayApp* app, + Controllers::HeartRateController& heartRateController, + System::SystemTask& systemTask) + : Screen(app), heartRateController {heartRateController}, systemTask {systemTask} { + bool isHrRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped; + label_hr = lv_label_create(lv_scr_act(), nullptr); + + lv_obj_set_style_local_text_font(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &neofont3); + + if (isHrRunning) + lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); + else + lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); + + lv_label_set_text(label_hr, "000"); + lv_obj_align(label_hr, nullptr, LV_ALIGN_CENTER, 0, -40); + + label_bpm = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text(label_bpm, "Heart rate BPM"); + lv_obj_align(label_bpm, label_hr, LV_ALIGN_OUT_TOP_MID, 0, -20); + + label_status = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(label_status, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x222222)); + lv_label_set_text(label_status, ToString(Pinetime::Controllers::HeartRateController::States::NotEnoughData)); + + lv_obj_align(label_status, label_hr, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); + + btn_startStop = lv_btn_create(lv_scr_act(), nullptr); + btn_startStop->user_data = this; + lv_obj_set_height(btn_startStop, 50); + lv_obj_set_event_cb(btn_startStop, btnStartStopEventHandler); + lv_obj_align(btn_startStop, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0); + + label_startStop = lv_label_create(btn_startStop, nullptr); + UpdateStartStopButton(isHrRunning); + if (isHrRunning) + systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); + + taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this); +} + +HeartRate::~HeartRate() { + lv_task_del(taskRefresh); + lv_obj_clean(lv_scr_act()); + systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); +} + +void HeartRate::Refresh() { + + auto state = heartRateController.State(); + switch (state) { + case Controllers::HeartRateController::States::NoTouch: + case Controllers::HeartRateController::States::NotEnoughData: + // case Controllers::HeartRateController::States::Stopped: + lv_label_set_text(label_hr, "000"); + break; + default: + lv_label_set_text_fmt(label_hr, "%03d", heartRateController.HeartRate()); + } + + lv_label_set_text(label_status, ToString(state)); + lv_obj_align(label_status, label_hr, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); +} + +void HeartRate::OnStartStopEvent(lv_event_t event) { + if (event == LV_EVENT_CLICKED) { + if (heartRateController.State() == Controllers::HeartRateController::States::Stopped) { + heartRateController.Start(); + UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped); + systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); + lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN); + } else { + heartRateController.Stop(); + UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped); + systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); + lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY); + } + } +} + +void HeartRate::UpdateStartStopButton(bool isRunning) { + if (isRunning) + lv_label_set_text(label_startStop, "Stop"); + else + lv_label_set_text(label_startStop, "Start"); +} diff --git a/src/displayapp/screens/HeartRate.h b/src/displayapp/screens/HeartRate.h new file mode 100644 index 0000000..2ad0035 --- /dev/null +++ b/src/displayapp/screens/HeartRate.h @@ -0,0 +1,40 @@ +#pragma once + +#include <cstdint> +#include <chrono> +#include "displayapp/screens/Screen.h" +#include "systemtask/SystemTask.h" +#include <lvgl/src/lv_core/lv_style.h> +#include <lvgl/src/lv_core/lv_obj.h> + +namespace Pinetime { + namespace Controllers { + class HeartRateController; + } + namespace Applications { + namespace Screens { + + class HeartRate : public Screen { + public: + HeartRate(DisplayApp* app, Controllers::HeartRateController& HeartRateController, System::SystemTask& systemTask); + ~HeartRate() override; + + void Refresh() override; + + void OnStartStopEvent(lv_event_t event); + + private: + Controllers::HeartRateController& heartRateController; + Pinetime::System::SystemTask& systemTask; + void UpdateStartStopButton(bool isRunning); + lv_obj_t* label_hr; + lv_obj_t* label_bpm; + lv_obj_t* label_status; + lv_obj_t* btn_startStop; + lv_obj_t* label_startStop; + + lv_task_t* taskRefresh; + }; + } + } +} diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index 963bfe4..44421ff 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -10,6 +10,7 @@ #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" +#include "components/heartrate/HeartRateController.h" #include "components/motion/MotionController.h" #include "components/settings/Settings.h" #include "displayapp/fonts/neofont.h" @@ -21,6 +22,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, Controllers::Ble& bleController, Controllers::NotificationManager& notificatioManager, Controllers::Settings& settingsController, + Controllers::HeartRateController& heartRateController, Controllers::MotionController& motionController, System::SystemTask& systemTask) : Screen(app), @@ -31,6 +33,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, bleController {bleController}, notificatioManager {notificatioManager}, settingsController {settingsController}, + heartRateController {heartRateController}, motionController {motionController} { if (1) { @@ -254,6 +257,16 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, lv_obj_set_pos(backgroundLabel, 0, 0); lv_label_set_text_static(backgroundLabel, ""); + heartbeatIcon = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text_static(heartbeatIcon, Symbols::heartBeat); + lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B)); + lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + + heartbeatValue = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B)); + lv_label_set_text_static(heartbeatValue, ""); + lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0); + taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); Refresh(); } @@ -380,4 +393,18 @@ void WatchFaceDigital::Refresh() { } } + heartbeat = heartRateController.HeartRate(); + heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped; + if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) { + if (heartbeatRunning.Get()) { + lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B)); + lv_label_set_text_fmt(heartbeatValue, "%d", heartbeat.Get()); + } else { + lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x1B1B1B)); + lv_label_set_text_static(heartbeatValue, ""); + } + + lv_obj_realign(heartbeatIcon); + lv_obj_realign(heartbeatValue); + } } diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h index 8382996..93719c1 100644 --- a/src/displayapp/screens/WatchFaceDigital.h +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -15,6 +15,7 @@ namespace Pinetime { class Battery; class Ble; class NotificationManager; + class HeartRateController; class MotionController; } @@ -29,6 +30,7 @@ namespace Pinetime { Controllers::Ble& bleController, Controllers::NotificationManager& notificatioManager, Controllers::Settings& settingsController, + Controllers::HeartRateController& heartRateController, Controllers::MotionController& motionController, System::SystemTask& systemTask); ~WatchFaceDigital() override; @@ -54,6 +56,8 @@ namespace Pinetime { DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime {}; DirtyValue<bool> motionSensorOk {}; DirtyValue<uint32_t> stepCount {}; + DirtyValue<uint8_t> heartbeat {}; + DirtyValue<bool> heartbeatRunning {}; DirtyValue<bool> notificationState {}; lv_obj_t* label_temp; @@ -68,6 +72,8 @@ namespace Pinetime { lv_obj_t* batteryIcon; lv_obj_t* bleIcon; lv_obj_t* batteryPlug; + lv_obj_t* heartbeatIcon; + lv_obj_t* heartbeatValue; lv_obj_t* stepIcon; lv_obj_t* stepValue; lv_obj_t* notificationIcon; @@ -77,6 +83,7 @@ namespace Pinetime { Controllers::Ble& bleController; Controllers::NotificationManager& notificatioManager; Controllers::Settings& settingsController; + Controllers::HeartRateController& heartRateController; Controllers::MotionController& motionController; lv_task_t* taskRefresh; |
