From 55086151e5493bf9108d9e39ccdb51d33fe6d122 Mon Sep 17 00:00:00 2001 From: JustScott Date: Sat, 3 Feb 2024 12:53:45 -0600 Subject: [PATCH 1/7] Terminal Watchface Improvements and added Weather. Use @vkareh's new weather forecast app as a template to implement the weather into the terminal watch face. Use InfintimeTheme Colors instead of hardcoded hex values. Reorder code to match the order of the UI. Implement @vkareh's variable battery icon color to the battery percentage text. Added a new IninftimeTheme color, gray, and turn certain values gray when they contain no data, like weather. --- src/displayapp/InfiniTimeTheme.h | 1 + src/displayapp/screens/WatchFaceTerminal.cpp | 165 ++++++++++++------- src/displayapp/screens/WatchFaceTerminal.h | 19 ++- src/displayapp/screens/WeatherSymbols.cpp | 20 +-- src/displayapp/screens/WeatherSymbols.h | 2 +- 5 files changed, 135 insertions(+), 72 deletions(-) diff --git a/src/displayapp/InfiniTimeTheme.h b/src/displayapp/InfiniTimeTheme.h index 0690b099..57680e87 100644 --- a/src/displayapp/InfiniTimeTheme.h +++ b/src/displayapp/InfiniTimeTheme.h @@ -8,6 +8,7 @@ namespace Colors { static constexpr lv_color_t green = LV_COLOR_MAKE(0x0, 0xb0, 0x0); static constexpr lv_color_t blue = LV_COLOR_MAKE(0x0, 0x50, 0xff); static constexpr lv_color_t lightGray = LV_COLOR_MAKE(0xb0, 0xb0, 0xb0); + static constexpr lv_color_t gray = LV_COLOR_MAKE(0x50, 0x50, 0x50); static constexpr lv_color_t bg = LV_COLOR_MAKE(0x5d, 0x69, 0x7e); static constexpr lv_color_t bgAlt = LV_COLOR_MAKE(0x38, 0x38, 0x38); diff --git a/src/displayapp/screens/WatchFaceTerminal.cpp b/src/displayapp/screens/WatchFaceTerminal.cpp index 96d77741..c7e11fc5 100644 --- a/src/displayapp/screens/WatchFaceTerminal.cpp +++ b/src/displayapp/screens/WatchFaceTerminal.cpp @@ -2,23 +2,40 @@ #include "displayapp/screens/WatchFaceTerminal.h" #include "displayapp/screens/BatteryIcon.h" #include "displayapp/screens/NotificationIcon.h" -#include "displayapp/screens/Symbols.h" #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" +#include "components/ble/SimpleWeatherService.h" #include "components/heartrate/HeartRateController.h" #include "components/motion/MotionController.h" #include "components/settings/Settings.h" +#include "displayapp/screens/WeatherSymbols.h" +#include "displayapp/InfiniTimeTheme.h" + using namespace Pinetime::Applications::Screens; +namespace { + lv_color_t temperatureColor(int16_t temperature) { + if (temperature <= 0) { // freezing + return Colors::blue; + } else if (temperature <= 400) { // ice + return LV_COLOR_CYAN; + } else if (temperature >= 2700) { // hot + return Colors::deepOrange; + } + return Colors::orange; // normal + } +} + WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController, const Controllers::Battery& batteryController, const Controllers::Ble& bleController, Controllers::NotificationManager& notificationManager, Controllers::Settings& settingsController, Controllers::HeartRateController& heartRateController, - Controllers::MotionController& motionController) + Controllers::MotionController& motionController, + Controllers::SimpleWeatherService& weatherService) : currentDateTime {{}}, dateTimeController {dateTimeController}, batteryController {batteryController}, @@ -26,41 +43,43 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController, notificationManager {notificationManager}, settingsController {settingsController}, heartRateController {heartRateController}, - motionController {motionController} { - batteryValue = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_recolor(batteryValue, true); - lv_obj_align(batteryValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20); - - connectState = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_recolor(connectState, true); - lv_obj_align(connectState, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 40); + motionController {motionController}, + weatherService {weatherService} { notificationIcon = lv_label_create(lv_scr_act(), nullptr); lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_LEFT_MID, 0, -100); - label_date = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_recolor(label_date, true); - lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -40); - label_prompt_1 = lv_label_create(lv_scr_act(), nullptr); lv_obj_align(label_prompt_1, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -80); lv_label_set_text_static(label_prompt_1, "user@watch:~ $ now"); - label_prompt_2 = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60); - lv_label_set_text_static(label_prompt_2, "user@watch:~ $"); - label_time = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_recolor(label_time, true); + lv_obj_set_style_local_text_color(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::blue); lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -60); - heartbeatValue = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_recolor(heartbeatValue, true); - lv_obj_align(heartbeatValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 20); + label_date = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(label_date, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::blue); + lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -40); + + weather = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(weather, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20); + + batteryValue = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(batteryValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0); stepValue = lv_label_create(lv_scr_act(), nullptr); - lv_label_set_recolor(stepValue, true); - lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0); + lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); + lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 20); + + heartbeatValue = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(heartbeatValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 40); + + connectState = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(connectState, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60); + + label_prompt_2 = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80); + lv_label_set_text_static(label_prompt_2, "user@watch:~ $"); taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); Refresh(); @@ -72,29 +91,6 @@ WatchFaceTerminal::~WatchFaceTerminal() { } void WatchFaceTerminal::Refresh() { - powerPresent = batteryController.IsPowerPresent(); - batteryPercentRemaining = batteryController.PercentRemaining(); - if (batteryPercentRemaining.IsUpdated() || powerPresent.IsUpdated()) { - lv_label_set_text_fmt(batteryValue, "[BATT]#387b54 %d%%", batteryPercentRemaining.Get()); - if (batteryController.IsPowerPresent()) { - lv_label_ins_text(batteryValue, LV_LABEL_POS_LAST, " Charging"); - } - } - - bleState = bleController.IsConnected(); - bleRadioEnabled = bleController.IsRadioEnabled(); - if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { - if (!bleRadioEnabled.Get()) { - lv_label_set_text_static(connectState, "[STAT]#0082fc Disabled#"); - } else { - if (bleState.Get()) { - lv_label_set_text_static(connectState, "[STAT]#0082fc Connected#"); - } else { - lv_label_set_text_static(connectState, "[STAT]#0082fc Disconnected#"); - } - } - } - notificationState = notificationManager.AreNewNotificationsAvailable(); if (notificationState.IsUpdated()) { if (notificationState.Get()) { @@ -104,6 +100,7 @@ void WatchFaceTerminal::Refresh() { } } + currentDateTime = std::chrono::time_point_cast(dateTimeController.CurrentDateTime()); if (currentDateTime.IsUpdated()) { uint8_t hour = dateTimeController.Hours(); @@ -120,9 +117,9 @@ void WatchFaceTerminal::Refresh() { hour = hour - 12; ampmChar[0] = 'P'; } - lv_label_set_text_fmt(label_time, "[TIME]#11cc55 %02d:%02d:%02d %s#", hour, minute, second, ampmChar); + lv_label_set_text_fmt(label_time, "[TIME] %02d:%02d:%02d %s#", hour, minute, second, ampmChar); } else { - lv_label_set_text_fmt(label_time, "[TIME]#11cc55 %02d:%02d:%02d", hour, minute, second); + lv_label_set_text_fmt(label_time, "[TIME] %02d:%02d:%02d", hour, minute, second); } currentDate = std::chrono::time_point_cast(currentDateTime.Get()); @@ -130,22 +127,80 @@ void WatchFaceTerminal::Refresh() { uint16_t year = dateTimeController.Year(); Controllers::DateTime::Months month = dateTimeController.Month(); uint8_t day = dateTimeController.Day(); - lv_label_set_text_fmt(label_date, "[DATE]#007fff %04d-%02d-%02d#", short(year), char(month), char(day)); + lv_label_set_text_fmt(label_date, "[DATE] %04d-%02d-%02d#", short(year), char(month), char(day)); } } + + + currentWeather = weatherService.Current(); + if (currentWeather.IsUpdated()) { + auto optCurrentWeather = currentWeather.Get(); + if (optCurrentWeather) { + int16_t temp = optCurrentWeather->temperature; + char tempUnit = 'C'; + lv_obj_set_style_local_text_color(weather, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, temperatureColor(temp)); + if (settingsController.GetWeatherFormat() == Controllers::Settings::WeatherFormat::Imperial) { + condition = Symbols::GetSimpleCondition(optCurrentWeather->iconId); + temp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(temp); + tempUnit = 'F'; + } + lv_label_set_text_fmt(weather, "[WTHR] %i°%c %s ", temp/100, tempUnit, condition); + } else { + lv_label_set_text(weather, "[WTHR] ---°"); + lv_obj_set_style_local_text_color(weather, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); + } + } + + + powerPresent = batteryController.IsPowerPresent(); + batteryPercentRemaining = batteryController.PercentRemaining(); + if (batteryPercentRemaining.IsUpdated() || powerPresent.IsUpdated()) { + // HSV color model has red at 0° and green at 120°. + // We lock satuation and brightness at 100% and traverse the cilinder + // between red and green, thus avoiding the darker RGB on medium battery + // charges and giving us a much nicer color range. + uint8_t hue = batteryPercentRemaining.Get() * 120 / 100; + lv_obj_set_style_local_text_color(batteryValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hsv_to_rgb(hue, 100, 100)); + lv_label_set_text_fmt(batteryValue, "[BATT] %d%%", batteryPercentRemaining.Get()); + if (batteryController.IsPowerPresent()) { + lv_label_ins_text(batteryValue, LV_LABEL_POS_LAST, " Charging"); + } + } + + + stepCount = motionController.NbSteps(); + if (stepCount.IsUpdated()) { + lv_label_set_text_fmt(stepValue, "[STEP] %lu steps#", stepCount.Get()); + } + heartbeat = heartRateController.HeartRate(); heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped; if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) { if (heartbeatRunning.Get()) { - lv_label_set_text_fmt(heartbeatValue, "[L_HR]#ee3311 %d bpm#", heartbeat.Get()); + + lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::deepOrange); + lv_label_set_text_fmt(heartbeatValue, "[L_HR] %d bpm#", heartbeat.Get()); } else { - lv_label_set_text_static(heartbeatValue, "[L_HR]#ee3311 ---#"); + lv_label_set_text_static(heartbeatValue, "[L_HR] ---#"); + lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); } } - stepCount = motionController.NbSteps(); - if (stepCount.IsUpdated()) { - lv_label_set_text_fmt(stepValue, "[STEP]#ee3377 %lu steps#", stepCount.Get()); + bleState = bleController.IsConnected(); + bleRadioEnabled = bleController.IsRadioEnabled(); + if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { + if (!bleRadioEnabled.Get()) { + lv_label_set_text_static(connectState, "[STAT] Disabled#"); + lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); + } else { + if (bleState.Get()) { + lv_label_set_text_static(connectState, "[STAT] Connected#"); + lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::blue); + } else { + lv_label_set_text_static(connectState, "[STAT] Disconnected#"); + lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); + } + } } } diff --git a/src/displayapp/screens/WatchFaceTerminal.h b/src/displayapp/screens/WatchFaceTerminal.h index bf460866..ee172073 100644 --- a/src/displayapp/screens/WatchFaceTerminal.h +++ b/src/displayapp/screens/WatchFaceTerminal.h @@ -7,6 +7,7 @@ #include #include "displayapp/screens/Screen.h" #include "components/datetime/DateTimeController.h" +#include "components/ble/SimpleWeatherService.h" #include "utility/DirtyValue.h" namespace Pinetime { @@ -30,7 +31,8 @@ namespace Pinetime { Controllers::NotificationManager& notificationManager, Controllers::Settings& settingsController, Controllers::HeartRateController& heartRateController, - Controllers::MotionController& motionController); + Controllers::MotionController& motionController, + Controllers::SimpleWeatherService& weatherService); ~WatchFaceTerminal() override; void Refresh() override; @@ -46,16 +48,19 @@ namespace Pinetime { Utility::DirtyValue heartbeatRunning {}; Utility::DirtyValue notificationState {}; Utility::DirtyValue> currentDate; + Utility::DirtyValue> currentWeather {}; + Utility::DirtyValue condition {}; + lv_obj_t* notificationIcon; + lv_obj_t* label_prompt_1; lv_obj_t* label_time; lv_obj_t* label_date; - lv_obj_t* label_prompt_1; - lv_obj_t* label_prompt_2; + lv_obj_t* weather; lv_obj_t* batteryValue; - lv_obj_t* heartbeatValue; lv_obj_t* stepValue; - lv_obj_t* notificationIcon; + lv_obj_t* heartbeatValue; lv_obj_t* connectState; + lv_obj_t* label_prompt_2; Controllers::DateTime& dateTimeController; const Controllers::Battery& batteryController; @@ -64,6 +69,7 @@ namespace Pinetime { Controllers::Settings& settingsController; Controllers::HeartRateController& heartRateController; Controllers::MotionController& motionController; + Controllers::SimpleWeatherService& weatherService; lv_task_t* taskRefresh; }; @@ -81,7 +87,8 @@ namespace Pinetime { controllers.notificationManager, controllers.settingsController, controllers.heartRateController, - controllers.motionController); + controllers.motionController, + *controllers.weatherController); }; static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) { diff --git a/src/displayapp/screens/WeatherSymbols.cpp b/src/displayapp/screens/WeatherSymbols.cpp index de66312f..d18c508a 100644 --- a/src/displayapp/screens/WeatherSymbols.cpp +++ b/src/displayapp/screens/WeatherSymbols.cpp @@ -35,26 +35,26 @@ const char* Pinetime::Applications::Screens::Symbols::GetSymbol(const Pinetime:: } } -const char* Pinetime::Applications::Screens::Symbols::GetCondition(const Pinetime::Controllers::SimpleWeatherService::Icons icon) { +const char* Pinetime::Applications::Screens::Symbols::GetSimpleCondition(const Pinetime::Controllers::SimpleWeatherService::Icons icon) { switch (icon) { case Pinetime::Controllers::SimpleWeatherService::Icons::Sun: - return "Clear sky"; + return "Clear"; case Pinetime::Controllers::SimpleWeatherService::Icons::CloudsSun: - return "Few clouds"; + return "Cloudy"; case Pinetime::Controllers::SimpleWeatherService::Icons::Clouds: - return "Scattered clouds"; + return "Cloudy"; case Pinetime::Controllers::SimpleWeatherService::Icons::BrokenClouds: - return "Broken clouds"; + return "Cloudy"; case Pinetime::Controllers::SimpleWeatherService::Icons::CloudShowerHeavy: - return "Shower rain"; + return "Rainy"; case Pinetime::Controllers::SimpleWeatherService::Icons::CloudSunRain: - return "Rain"; + return "Rainy"; case Pinetime::Controllers::SimpleWeatherService::Icons::Thunderstorm: - return "Thunderstorm"; + return "Stormy"; case Pinetime::Controllers::SimpleWeatherService::Icons::Snow: - return "Snow"; + return "Snowy"; case Pinetime::Controllers::SimpleWeatherService::Icons::Smog: - return "Mist"; + return "Misty"; default: return ""; } diff --git a/src/displayapp/screens/WeatherSymbols.h b/src/displayapp/screens/WeatherSymbols.h index f3eeed55..0e9b08ee 100644 --- a/src/displayapp/screens/WeatherSymbols.h +++ b/src/displayapp/screens/WeatherSymbols.h @@ -7,7 +7,7 @@ namespace Pinetime { namespace Screens { namespace Symbols { const char* GetSymbol(const Pinetime::Controllers::SimpleWeatherService::Icons icon); - const char* GetCondition(const Pinetime::Controllers::SimpleWeatherService::Icons icon); + const char* GetSimpleCondition(const Pinetime::Controllers::SimpleWeatherService::Icons icon); } } } From 53c53c6512cb104a573da7bcd72c28008dae022d Mon Sep 17 00:00:00 2001 From: JustScott Date: Sat, 3 Feb 2024 14:06:27 -0600 Subject: [PATCH 2/7] Updated date, time, and prompt colors --- src/displayapp/screens/WatchFaceTerminal.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/WatchFaceTerminal.cpp b/src/displayapp/screens/WatchFaceTerminal.cpp index c7e11fc5..b888580e 100644 --- a/src/displayapp/screens/WatchFaceTerminal.cpp +++ b/src/displayapp/screens/WatchFaceTerminal.cpp @@ -50,15 +50,14 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController, lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_LEFT_MID, 0, -100); label_prompt_1 = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(label_prompt_1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); lv_obj_align(label_prompt_1, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -80); lv_label_set_text_static(label_prompt_1, "user@watch:~ $ now"); label_time = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::blue); lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -60); label_date = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(label_date, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::blue); lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -40); weather = lv_label_create(lv_scr_act(), nullptr); @@ -78,6 +77,7 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController, lv_obj_align(connectState, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60); label_prompt_2 = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(label_prompt_2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::lightGray); lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80); lv_label_set_text_static(label_prompt_2, "user@watch:~ $"); From faae3e0ff52005e064d9fd3dbc81a791c06eb4bc Mon Sep 17 00:00:00 2001 From: JustScott Date: Sat, 3 Feb 2024 14:13:58 -0600 Subject: [PATCH 3/7] Removed random #'s from the text values --- src/displayapp/screens/WatchFaceTerminal.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/displayapp/screens/WatchFaceTerminal.cpp b/src/displayapp/screens/WatchFaceTerminal.cpp index b888580e..dc9a19b4 100644 --- a/src/displayapp/screens/WatchFaceTerminal.cpp +++ b/src/displayapp/screens/WatchFaceTerminal.cpp @@ -117,7 +117,7 @@ void WatchFaceTerminal::Refresh() { hour = hour - 12; ampmChar[0] = 'P'; } - lv_label_set_text_fmt(label_time, "[TIME] %02d:%02d:%02d %s#", hour, minute, second, ampmChar); + lv_label_set_text_fmt(label_time, "[TIME] %02d:%02d:%02d %s", hour, minute, second, ampmChar); } else { lv_label_set_text_fmt(label_time, "[TIME] %02d:%02d:%02d", hour, minute, second); } @@ -127,7 +127,7 @@ void WatchFaceTerminal::Refresh() { uint16_t year = dateTimeController.Year(); Controllers::DateTime::Months month = dateTimeController.Month(); uint8_t day = dateTimeController.Day(); - lv_label_set_text_fmt(label_date, "[DATE] %04d-%02d-%02d#", short(year), char(month), char(day)); + lv_label_set_text_fmt(label_date, "[DATE] %04d-%02d-%02d", short(year), char(month), char(day)); } } @@ -170,7 +170,7 @@ void WatchFaceTerminal::Refresh() { stepCount = motionController.NbSteps(); if (stepCount.IsUpdated()) { - lv_label_set_text_fmt(stepValue, "[STEP] %lu steps#", stepCount.Get()); + lv_label_set_text_fmt(stepValue, "[STEP] %lu steps", stepCount.Get()); } @@ -180,9 +180,9 @@ void WatchFaceTerminal::Refresh() { if (heartbeatRunning.Get()) { lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::deepOrange); - lv_label_set_text_fmt(heartbeatValue, "[L_HR] %d bpm#", heartbeat.Get()); + lv_label_set_text_fmt(heartbeatValue, "[L_HR] %d bpm", heartbeat.Get()); } else { - lv_label_set_text_static(heartbeatValue, "[L_HR] ---#"); + lv_label_set_text_static(heartbeatValue, "[L_HR] ---"); lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); } } @@ -191,14 +191,14 @@ void WatchFaceTerminal::Refresh() { bleRadioEnabled = bleController.IsRadioEnabled(); if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { if (!bleRadioEnabled.Get()) { - lv_label_set_text_static(connectState, "[STAT] Disabled#"); + lv_label_set_text_static(connectState, "[STAT] Disabled"); lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); } else { if (bleState.Get()) { - lv_label_set_text_static(connectState, "[STAT] Connected#"); + lv_label_set_text_static(connectState, "[STAT] Connected"); lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::blue); } else { - lv_label_set_text_static(connectState, "[STAT] Disconnected#"); + lv_label_set_text_static(connectState, "[STAT] Disconnected"); lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); } } From 833b8d693ff79a78e6268b2c5694901fd5f2ec1d Mon Sep 17 00:00:00 2001 From: JustScott Date: Sun, 4 Feb 2024 11:31:40 -0600 Subject: [PATCH 4/7] Updated terminal coloring Labels are now a static white #ffffff, while the values can still dynamically change color. --- src/displayapp/screens/WatchFaceTerminal.cpp | 37 ++++++++++---------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/displayapp/screens/WatchFaceTerminal.cpp b/src/displayapp/screens/WatchFaceTerminal.cpp index dc9a19b4..23a3a063 100644 --- a/src/displayapp/screens/WatchFaceTerminal.cpp +++ b/src/displayapp/screens/WatchFaceTerminal.cpp @@ -12,7 +12,6 @@ #include "displayapp/screens/WeatherSymbols.h" #include "displayapp/InfiniTimeTheme.h" - using namespace Pinetime::Applications::Screens; namespace { @@ -55,25 +54,32 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController, lv_label_set_text_static(label_prompt_1, "user@watch:~ $ now"); label_time = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(label_time, true); lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -60); label_date = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(label_date, true); lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -40); weather = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(weather, true); lv_obj_align(weather, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20); batteryValue = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(batteryValue, true); lv_obj_align(batteryValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0); stepValue = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(stepValue, true); lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::orange); lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 20); heartbeatValue = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(heartbeatValue, true); lv_obj_align(heartbeatValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 40); connectState = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(connectState, true); lv_obj_align(connectState, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60); label_prompt_2 = lv_label_create(lv_scr_act(), nullptr); @@ -100,7 +106,6 @@ void WatchFaceTerminal::Refresh() { } } - currentDateTime = std::chrono::time_point_cast(dateTimeController.CurrentDateTime()); if (currentDateTime.IsUpdated()) { uint8_t hour = dateTimeController.Hours(); @@ -117,9 +122,9 @@ void WatchFaceTerminal::Refresh() { hour = hour - 12; ampmChar[0] = 'P'; } - lv_label_set_text_fmt(label_time, "[TIME] %02d:%02d:%02d %s", hour, minute, second, ampmChar); + lv_label_set_text_fmt(label_time, "#fffff [TIME]# #11cc55 %02d:%02d:%02d %s#", hour, minute, second, ampmChar); } else { - lv_label_set_text_fmt(label_time, "[TIME] %02d:%02d:%02d", hour, minute, second); + lv_label_set_text_fmt(label_time, "#ffffff [TIME]# #11cc55 %02d:%02d:%02d#", hour, minute, second); } currentDate = std::chrono::time_point_cast(currentDateTime.Get()); @@ -127,10 +132,9 @@ void WatchFaceTerminal::Refresh() { uint16_t year = dateTimeController.Year(); Controllers::DateTime::Months month = dateTimeController.Month(); uint8_t day = dateTimeController.Day(); - lv_label_set_text_fmt(label_date, "[DATE] %04d-%02d-%02d", short(year), char(month), char(day)); + lv_label_set_text_fmt(label_date, "#ffffff [DATE]# #007fff %04d-%02d-%02d#", short(year), char(month), char(day)); } } - currentWeather = weatherService.Current(); if (currentWeather.IsUpdated()) { @@ -144,14 +148,13 @@ void WatchFaceTerminal::Refresh() { temp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(temp); tempUnit = 'F'; } - lv_label_set_text_fmt(weather, "[WTHR] %i°%c %s ", temp/100, tempUnit, condition); + lv_label_set_text_fmt(weather, "#ffffff [WTHR]# %i°%c %s ", temp / 100, tempUnit, condition); } else { - lv_label_set_text(weather, "[WTHR] ---°"); + lv_label_set_text(weather, "#ffffff [WTHR]# ---"); lv_obj_set_style_local_text_color(weather, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); } } - powerPresent = batteryController.IsPowerPresent(); batteryPercentRemaining = batteryController.PercentRemaining(); if (batteryPercentRemaining.IsUpdated() || powerPresent.IsUpdated()) { @@ -161,28 +164,26 @@ void WatchFaceTerminal::Refresh() { // charges and giving us a much nicer color range. uint8_t hue = batteryPercentRemaining.Get() * 120 / 100; lv_obj_set_style_local_text_color(batteryValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hsv_to_rgb(hue, 100, 100)); - lv_label_set_text_fmt(batteryValue, "[BATT] %d%%", batteryPercentRemaining.Get()); + lv_label_set_text_fmt(batteryValue, "#ffffff [BATT]# %d%%", batteryPercentRemaining.Get()); if (batteryController.IsPowerPresent()) { lv_label_ins_text(batteryValue, LV_LABEL_POS_LAST, " Charging"); } } - stepCount = motionController.NbSteps(); if (stepCount.IsUpdated()) { - lv_label_set_text_fmt(stepValue, "[STEP] %lu steps", stepCount.Get()); + lv_label_set_text_fmt(stepValue, "#ffffff [STEP]# %lu steps", stepCount.Get()); } - 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(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::deepOrange); - lv_label_set_text_fmt(heartbeatValue, "[L_HR] %d bpm", heartbeat.Get()); + lv_label_set_text_fmt(heartbeatValue, "#ffffff [L_HR]# %d bpm", heartbeat.Get()); } else { - lv_label_set_text_static(heartbeatValue, "[L_HR] ---"); + lv_label_set_text_static(heartbeatValue, "#ffffff [L_HR]# ---"); lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); } } @@ -191,14 +192,14 @@ void WatchFaceTerminal::Refresh() { bleRadioEnabled = bleController.IsRadioEnabled(); if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { if (!bleRadioEnabled.Get()) { - lv_label_set_text_static(connectState, "[STAT] Disabled"); + lv_label_set_text_static(connectState, "#ffffff [STAT]# Disabled"); lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); } else { if (bleState.Get()) { - lv_label_set_text_static(connectState, "[STAT] Connected"); + lv_label_set_text_static(connectState, "#ffffff [STAT]# Connected"); lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::blue); } else { - lv_label_set_text_static(connectState, "[STAT] Disconnected"); + lv_label_set_text_static(connectState, "#ffffff [STAT]# Disconnected"); lv_obj_set_style_local_text_color(connectState, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); } } From 118905325fdb3ac1869b22a4656932f54cde160e Mon Sep 17 00:00:00 2001 From: JustScott Date: Mon, 5 Feb 2024 15:35:40 -0600 Subject: [PATCH 5/7] Pass the value for the weather condition variable directly instead of defining it first. changed the 'you have mail' to '[1]+ Notify, to better align with terminal lore. Use `IsCharging` instead of `IsPowerPresent` to stop displaying the 'Charging' text once the battery's full. Update the return values for weather condition in `GetSimpleCondition` to match the standard names used in the rest of the project. --- src/displayapp/screens/WatchFaceTerminal.cpp | 7 +++---- src/displayapp/screens/WatchFaceTerminal.h | 1 - src/displayapp/screens/WeatherSymbols.cpp | 16 ++++++++-------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/displayapp/screens/WatchFaceTerminal.cpp b/src/displayapp/screens/WatchFaceTerminal.cpp index 23a3a063..870459bf 100644 --- a/src/displayapp/screens/WatchFaceTerminal.cpp +++ b/src/displayapp/screens/WatchFaceTerminal.cpp @@ -100,7 +100,7 @@ void WatchFaceTerminal::Refresh() { notificationState = notificationManager.AreNewNotificationsAvailable(); if (notificationState.IsUpdated()) { if (notificationState.Get()) { - lv_label_set_text_static(notificationIcon, "You have mail."); + lv_label_set_text_static(notificationIcon, "[1]+ Notify"); } else { lv_label_set_text_static(notificationIcon, ""); } @@ -144,11 +144,10 @@ void WatchFaceTerminal::Refresh() { char tempUnit = 'C'; lv_obj_set_style_local_text_color(weather, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, temperatureColor(temp)); if (settingsController.GetWeatherFormat() == Controllers::Settings::WeatherFormat::Imperial) { - condition = Symbols::GetSimpleCondition(optCurrentWeather->iconId); temp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(temp); tempUnit = 'F'; } - lv_label_set_text_fmt(weather, "#ffffff [WTHR]# %i°%c %s ", temp / 100, tempUnit, condition); + lv_label_set_text_fmt(weather, "#ffffff [WTHR]# %i°%c %s ", temp / 100, tempUnit, Symbols::GetSimpleCondition(optCurrentWeather->iconId)); } else { lv_label_set_text(weather, "#ffffff [WTHR]# ---"); lv_obj_set_style_local_text_color(weather, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray); @@ -165,7 +164,7 @@ void WatchFaceTerminal::Refresh() { uint8_t hue = batteryPercentRemaining.Get() * 120 / 100; lv_obj_set_style_local_text_color(batteryValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hsv_to_rgb(hue, 100, 100)); lv_label_set_text_fmt(batteryValue, "#ffffff [BATT]# %d%%", batteryPercentRemaining.Get()); - if (batteryController.IsPowerPresent()) { + if (batteryController.IsCharging()) { lv_label_ins_text(batteryValue, LV_LABEL_POS_LAST, " Charging"); } } diff --git a/src/displayapp/screens/WatchFaceTerminal.h b/src/displayapp/screens/WatchFaceTerminal.h index ee172073..ee1370d4 100644 --- a/src/displayapp/screens/WatchFaceTerminal.h +++ b/src/displayapp/screens/WatchFaceTerminal.h @@ -49,7 +49,6 @@ namespace Pinetime { Utility::DirtyValue notificationState {}; Utility::DirtyValue> currentDate; Utility::DirtyValue> currentWeather {}; - Utility::DirtyValue condition {}; lv_obj_t* notificationIcon; lv_obj_t* label_prompt_1; diff --git a/src/displayapp/screens/WeatherSymbols.cpp b/src/displayapp/screens/WeatherSymbols.cpp index d18c508a..2f3535d3 100644 --- a/src/displayapp/screens/WeatherSymbols.cpp +++ b/src/displayapp/screens/WeatherSymbols.cpp @@ -40,21 +40,21 @@ const char* Pinetime::Applications::Screens::Symbols::GetSimpleCondition(const P case Pinetime::Controllers::SimpleWeatherService::Icons::Sun: return "Clear"; case Pinetime::Controllers::SimpleWeatherService::Icons::CloudsSun: - return "Cloudy"; + return "Clouds"; case Pinetime::Controllers::SimpleWeatherService::Icons::Clouds: - return "Cloudy"; + return "Clouds"; case Pinetime::Controllers::SimpleWeatherService::Icons::BrokenClouds: - return "Cloudy"; + return "Clouds"; case Pinetime::Controllers::SimpleWeatherService::Icons::CloudShowerHeavy: - return "Rainy"; + return "Rain"; case Pinetime::Controllers::SimpleWeatherService::Icons::CloudSunRain: - return "Rainy"; + return "Drizzle"; case Pinetime::Controllers::SimpleWeatherService::Icons::Thunderstorm: - return "Stormy"; + return "Thunder"; case Pinetime::Controllers::SimpleWeatherService::Icons::Snow: - return "Snowy"; + return "Snow"; case Pinetime::Controllers::SimpleWeatherService::Icons::Smog: - return "Misty"; + return "Mist"; default: return ""; } From 3341247788abccc071238aaf637e552c21a04142 Mon Sep 17 00:00:00 2001 From: JustScott Date: Tue, 20 Feb 2024 18:13:13 -0600 Subject: [PATCH 6/7] Rebase with upstream & Fix conflicts --- src/displayapp/screens/WeatherSymbols.cpp | 25 +++++++++++++++++++++++ src/displayapp/screens/WeatherSymbols.h | 1 + 2 files changed, 26 insertions(+) diff --git a/src/displayapp/screens/WeatherSymbols.cpp b/src/displayapp/screens/WeatherSymbols.cpp index 2f3535d3..7a9272d9 100644 --- a/src/displayapp/screens/WeatherSymbols.cpp +++ b/src/displayapp/screens/WeatherSymbols.cpp @@ -35,6 +35,31 @@ const char* Pinetime::Applications::Screens::Symbols::GetSymbol(const Pinetime:: } } +const char* Pinetime::Applications::Screens::Symbols::GetCondition(const Pinetime::Controllers::SimpleWeatherService::Icons icon) { + switch (icon) { + case Pinetime::Controllers::SimpleWeatherService::Icons::Sun: + return "Clear sky"; + case Pinetime::Controllers::SimpleWeatherService::Icons::CloudsSun: + return "Few clouds"; + case Pinetime::Controllers::SimpleWeatherService::Icons::Clouds: + return "Scattered clouds"; + case Pinetime::Controllers::SimpleWeatherService::Icons::BrokenClouds: + return "Broken clouds"; + case Pinetime::Controllers::SimpleWeatherService::Icons::CloudShowerHeavy: + return "Shower rain"; + case Pinetime::Controllers::SimpleWeatherService::Icons::CloudSunRain: + return "Rain"; + case Pinetime::Controllers::SimpleWeatherService::Icons::Thunderstorm: + return "Thunderstorm"; + case Pinetime::Controllers::SimpleWeatherService::Icons::Snow: + return "Snow"; + case Pinetime::Controllers::SimpleWeatherService::Icons::Smog: + return "Mist"; + default: + return ""; + } +} + const char* Pinetime::Applications::Screens::Symbols::GetSimpleCondition(const Pinetime::Controllers::SimpleWeatherService::Icons icon) { switch (icon) { case Pinetime::Controllers::SimpleWeatherService::Icons::Sun: diff --git a/src/displayapp/screens/WeatherSymbols.h b/src/displayapp/screens/WeatherSymbols.h index 0e9b08ee..0fed0bdc 100644 --- a/src/displayapp/screens/WeatherSymbols.h +++ b/src/displayapp/screens/WeatherSymbols.h @@ -7,6 +7,7 @@ namespace Pinetime { namespace Screens { namespace Symbols { const char* GetSymbol(const Pinetime::Controllers::SimpleWeatherService::Icons icon); + const char* GetCondition(const Pinetime::Controllers::SimpleWeatherService::Icons icon); const char* GetSimpleCondition(const Pinetime::Controllers::SimpleWeatherService::Icons icon); } } From b30f6c07b9530e213d2d6a8d9711e263cedf19e0 Mon Sep 17 00:00:00 2001 From: JustScott Date: Thu, 3 Oct 2024 14:28:49 -0500 Subject: [PATCH 7/7] Fix code formatting with 'clang-format' --- src/displayapp/screens/WatchFaceTerminal.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/displayapp/screens/WatchFaceTerminal.cpp b/src/displayapp/screens/WatchFaceTerminal.cpp index 870459bf..80445d83 100644 --- a/src/displayapp/screens/WatchFaceTerminal.cpp +++ b/src/displayapp/screens/WatchFaceTerminal.cpp @@ -147,7 +147,11 @@ void WatchFaceTerminal::Refresh() { temp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(temp); tempUnit = 'F'; } - lv_label_set_text_fmt(weather, "#ffffff [WTHR]# %i°%c %s ", temp / 100, tempUnit, Symbols::GetSimpleCondition(optCurrentWeather->iconId)); + lv_label_set_text_fmt(weather, + "#ffffff [WTHR]# %i°%c %s ", + temp / 100, + tempUnit, + Symbols::GetSimpleCondition(optCurrentWeather->iconId)); } else { lv_label_set_text(weather, "#ffffff [WTHR]# ---"); lv_obj_set_style_local_text_color(weather, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Colors::gray);