From ff352f4e36c48622fcc67b54f222615e4b049c29 Mon Sep 17 00:00:00 2001 From: Julian Vos Date: Sat, 3 Aug 2024 17:46:42 +0200 Subject: [PATCH 01/11] chore: ignore node_modules --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 81e49ae083..14872a71c1 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,5 @@ src/arm-none-eabi # clangd .cache/ + +node_modules/ \ No newline at end of file From ffff67af3313e84fd4cc13f476346b6e66e5cbac Mon Sep 17 00:00:00 2001 From: Julian Vos Date: Sat, 3 Aug 2024 17:54:30 +0200 Subject: [PATCH 02/11] feat: add notification and chime vibration settings --- src/CMakeLists.txt | 2 + src/components/settings/Settings.h | 26 +++++++ src/displayapp/DisplayApp.cpp | 16 ++++- src/displayapp/apps/Apps.h.in | 2 + src/displayapp/screens/Notifications.cpp | 3 +- src/displayapp/screens/Notifications.h | 1 + .../settings/SettingChimeVibration.cpp | 70 +++++++++++++++++++ .../screens/settings/SettingChimeVibration.h | 30 ++++++++ .../settings/SettingNotifVibration.cpp | 69 ++++++++++++++++++ .../screens/settings/SettingNotifVibration.h | 30 ++++++++ src/displayapp/screens/settings/Settings.h | 4 +- 11 files changed, 248 insertions(+), 5 deletions(-) create mode 100644 src/displayapp/screens/settings/SettingChimeVibration.cpp create mode 100644 src/displayapp/screens/settings/SettingChimeVibration.h create mode 100644 src/displayapp/screens/settings/SettingNotifVibration.cpp create mode 100644 src/displayapp/screens/settings/SettingNotifVibration.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fd8ece62a6..d73fcb1522 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -418,6 +418,8 @@ list(APPEND SOURCE_FILES displayapp/screens/settings/SettingChimes.cpp displayapp/screens/settings/SettingShakeThreshold.cpp displayapp/screens/settings/SettingBluetooth.cpp + displayapp/screens/settings/SettingNotifVibration.cpp + displayapp/screens/settings/SettingChimeVibration.cpp ## Watch faces displayapp/screens/WatchFaceAnalog.cpp diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 063120774a..7875189c20 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -34,6 +34,7 @@ namespace Pinetime { Orange, Pink }; + enum class VibrationStrength : uint8_t { Weak = 15, Normal = 35, Strong = 75 }; enum class PTSGaugeStyle : uint8_t { Full, Half, Numeric }; enum class PTSWeather : uint8_t { On, Off }; @@ -283,6 +284,28 @@ namespace Pinetime { return bleRadioEnabled; }; + void SetNotifVibration(VibrationStrength strength) { + if (strength != settings.notifVibration) { + settingsChanged = true; + } + settings.notifVibration = strength; + }; + + VibrationStrength GetNotifVibration() const { + return settings.notifVibration; + } + + void SetChimeVibration(VibrationStrength strength) { + if (strength != settings.chimeVibration) { + settingsChanged = true; + } + settings.chimeVibration = strength; + }; + + VibrationStrength GetChimeVibration() const { + return settings.chimeVibration; + } + private: Pinetime::Controllers::FS& fs; @@ -308,6 +331,9 @@ namespace Pinetime { uint16_t shakeWakeThreshold = 150; Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; + + VibrationStrength notifVibration = VibrationStrength::Normal; + VibrationStrength chimeVibration = VibrationStrength::Normal; }; SettingsData settings; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 3fd34b3a8c..83bb739052 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -49,6 +49,8 @@ #include "displayapp/screens/settings/SettingChimes.h" #include "displayapp/screens/settings/SettingShakeThreshold.h" #include "displayapp/screens/settings/SettingBluetooth.h" +#include "displayapp/screens/settings/SettingNotifVibration.h" +#include "displayapp/screens/settings/SettingChimeVibration.h" #include "libs/lv_conf.h" #include "UserApps.h" @@ -270,7 +272,7 @@ void DisplayApp::Refresh() { } else { LoadNewScreen(Apps::Timer, DisplayApp::FullRefreshDirections::Up); } - motorController.RunForDuration(35); + motorController.RunForDuration(static_cast(settingsController.GetNotifVibration())); break; case Messages::AlarmTriggered: if (currentApp == Apps::Alarm) { @@ -282,7 +284,7 @@ void DisplayApp::Refresh() { break; case Messages::ShowPairingKey: LoadNewScreen(Apps::PassKey, DisplayApp::FullRefreshDirections::Up); - motorController.RunForDuration(35); + motorController.RunForDuration(static_cast(settingsController.GetNotifVibration())); break; case Messages::TouchEvent: { if (state != States::Running) { @@ -375,7 +377,7 @@ void DisplayApp::Refresh() { break; case Messages::Chime: LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::None); - motorController.RunForDuration(35); + motorController.RunForDuration(static_cast(settingsController.GetChimeVibration())); break; case Messages::OnChargingEvent: RestoreBrightness(); @@ -465,6 +467,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio notificationManager, systemTask->nimble().alertService(), motorController, + settingsController, *systemTask, Screens::Notifications::Modes::Normal); break; @@ -473,6 +476,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio notificationManager, systemTask->nimble().alertService(), motorController, + settingsController, *systemTask, Screens::Notifications::Modes::Preview); break; @@ -524,6 +528,12 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio case Apps::SettingBluetooth: currentScreen = std::make_unique(this, settingsController); break; + case Apps::SettingNotifVibration: + currentScreen = std::make_unique(settingsController, motorController); + break; + case Apps::SettingChimeVibration: + currentScreen = std::make_unique(settingsController, motorController); + break; case Apps::BatteryInfo: currentScreen = std::make_unique(batteryController); break; diff --git a/src/displayapp/apps/Apps.h.in b/src/displayapp/apps/Apps.h.in index 2104a267c0..3f40137507 100644 --- a/src/displayapp/apps/Apps.h.in +++ b/src/displayapp/apps/Apps.h.in @@ -42,6 +42,8 @@ namespace Pinetime { SettingChimes, SettingShakeThreshold, SettingBluetooth, + SettingNotifVibration, + SettingChimeVibration, Error }; diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp index 037c43a7f6..2f710300fb 100644 --- a/src/displayapp/screens/Notifications.cpp +++ b/src/displayapp/screens/Notifications.cpp @@ -14,6 +14,7 @@ Notifications::Notifications(DisplayApp* app, Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, Pinetime::Controllers::MotorController& motorController, + Pinetime::Controllers::Settings& settingsController, System::SystemTask& systemTask, Modes mode) : app {app}, @@ -44,7 +45,7 @@ Notifications::Notifications(DisplayApp* app, if (notification.category == Controllers::NotificationManager::Categories::IncomingCall) { motorController.StartRinging(); } else { - motorController.RunForDuration(35); + motorController.RunForDuration(static_cast(settingsController.GetNotifVibration())); } timeoutLine = lv_line_create(lv_scr_act(), nullptr); diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h index 114316b35b..5eedd591d4 100644 --- a/src/displayapp/screens/Notifications.h +++ b/src/displayapp/screens/Notifications.h @@ -24,6 +24,7 @@ namespace Pinetime { Pinetime::Controllers::NotificationManager& notificationManager, Pinetime::Controllers::AlertNotificationService& alertNotificationService, Pinetime::Controllers::MotorController& motorController, + Pinetime::Controllers::Settings& settingsController, System::SystemTask& systemTask, Modes mode); ~Notifications() override; diff --git a/src/displayapp/screens/settings/SettingChimeVibration.cpp b/src/displayapp/screens/settings/SettingChimeVibration.cpp new file mode 100644 index 0000000000..e46d637c42 --- /dev/null +++ b/src/displayapp/screens/settings/SettingChimeVibration.cpp @@ -0,0 +1,70 @@ +#include "displayapp/screens/settings/SettingChimeVibration.h" + +#include + +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/Styles.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/Symbols.h" + +using namespace Pinetime::Applications::Screens; + +namespace { + struct Option { + Pinetime::Controllers::Settings::VibrationStrength vibrationStrength; + const char* name; + }; + + constexpr std::array options = {{ + {Pinetime::Controllers::Settings::VibrationStrength::Weak, "Weak"}, + {Pinetime::Controllers::Settings::VibrationStrength::Normal, "Normal"}, + {Pinetime::Controllers::Settings::VibrationStrength::Strong, "Strong"}, + }}; + + std::array CreateOptionArray() { + std::array optionArray; + for (size_t i = 0; i < CheckboxList::MaxItems; i++) { + if (i >= options.size()) { + optionArray[i].name = ""; + optionArray[i].enabled = false; + } else { + optionArray[i].name = options[i].name; + optionArray[i].enabled = true; + } + } + return optionArray; + } + + uint32_t GetDefaultOption(Pinetime::Controllers::Settings::VibrationStrength currentOption) { + for (size_t i = 0; i < options.size(); i++) { + if (options[i].vibrationStrength == currentOption) { + return i; + } + } + return 0; + } +} + +SettingChimeVibration::SettingChimeVibration( + Pinetime::Controllers::Settings& settingsController, + Pinetime::Controllers::MotorController& motorController +) + : checkboxList( + 0, + 1, + "Chime strength", + Symbols::tachometer, + GetDefaultOption(settingsController.GetChimeVibration()), + [&settings = settingsController, &motor = motorController](uint32_t index) { + // Preview current setting + motor.RunForDuration(static_cast(options[index].vibrationStrength)); + + settings.SetChimeVibration(options[index].vibrationStrength); + settings.SaveSettings(); + }, + CreateOptionArray()) { +} + +SettingChimeVibration::~SettingChimeVibration() { + lv_obj_clean(lv_scr_act()); +} \ No newline at end of file diff --git a/src/displayapp/screens/settings/SettingChimeVibration.h b/src/displayapp/screens/settings/SettingChimeVibration.h new file mode 100644 index 0000000000..e27933731b --- /dev/null +++ b/src/displayapp/screens/settings/SettingChimeVibration.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +#include "components/settings/Settings.h" +#include "components/motor/MotorController.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/CheckboxList.h" + +namespace Pinetime { + + namespace Applications { + namespace Screens { + + class SettingChimeVibration : public Screen { + public: + explicit SettingChimeVibration( + Pinetime::Controllers::Settings& settingsController, + Pinetime::Controllers::MotorController& motorController + ); + ~SettingChimeVibration() override; + + private: + CheckboxList checkboxList; + }; + } + } +} \ No newline at end of file diff --git a/src/displayapp/screens/settings/SettingNotifVibration.cpp b/src/displayapp/screens/settings/SettingNotifVibration.cpp new file mode 100644 index 0000000000..1665e89b69 --- /dev/null +++ b/src/displayapp/screens/settings/SettingNotifVibration.cpp @@ -0,0 +1,69 @@ +#include "displayapp/screens/settings/SettingNotifVibration.h" + +#include + +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/Styles.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/Symbols.h" + +using namespace Pinetime::Applications::Screens; + +namespace { + struct Option { + Pinetime::Controllers::Settings::VibrationStrength vibrationStrength; + const char* name; + }; + + constexpr std::array options = {{ + {Pinetime::Controllers::Settings::VibrationStrength::Weak, "Weak"}, + {Pinetime::Controllers::Settings::VibrationStrength::Normal, "Normal"}, + {Pinetime::Controllers::Settings::VibrationStrength::Strong, "Strong"}, + }}; + + std::array CreateOptionArray() { + std::array optionArray; + for (size_t i = 0; i < CheckboxList::MaxItems; i++) { + if (i >= options.size()) { + optionArray[i].name = ""; + optionArray[i].enabled = false; + } else { + optionArray[i].name = options[i].name; + optionArray[i].enabled = true; + } + } + return optionArray; + } + + uint32_t GetDefaultOption(Pinetime::Controllers::Settings::VibrationStrength currentOption) { + for (size_t i = 0; i < options.size(); i++) { + if (options[i].vibrationStrength == currentOption) { + return i; + } + } + return 0; + } +} + +SettingNotifVibration::SettingNotifVibration( + Pinetime::Controllers::Settings& settingsController, + Pinetime::Controllers::MotorController& motorController +) + : checkboxList( + 0, + 1, + "Notif. strength", + Symbols::tachometer, + GetDefaultOption(settingsController.GetNotifVibration()), + [&settings = settingsController, &motor = motorController](uint32_t index) { + motor.RunForDuration(static_cast(options[index].vibrationStrength)); + + settings.SetNotifVibration(options[index].vibrationStrength); + settings.SaveSettings(); + }, + CreateOptionArray()) { +} + +SettingNotifVibration::~SettingNotifVibration() { + lv_obj_clean(lv_scr_act()); +} \ No newline at end of file diff --git a/src/displayapp/screens/settings/SettingNotifVibration.h b/src/displayapp/screens/settings/SettingNotifVibration.h new file mode 100644 index 0000000000..7f078b22f3 --- /dev/null +++ b/src/displayapp/screens/settings/SettingNotifVibration.h @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include + +#include "components/settings/Settings.h" +#include "components/motor/MotorController.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/CheckboxList.h" + +namespace Pinetime { + + namespace Applications { + namespace Screens { + + class SettingNotifVibration : public Screen { + public: + explicit SettingNotifVibration( + Pinetime::Controllers::Settings& settingsController, + Pinetime::Controllers::MotorController& motorController + ); + ~SettingNotifVibration() override; + + private: + CheckboxList checkboxList; + }; + } + } +} \ No newline at end of file diff --git a/src/displayapp/screens/settings/Settings.h b/src/displayapp/screens/settings/Settings.h index a21b4ccd85..fa1fdd5a21 100644 --- a/src/displayapp/screens/settings/Settings.h +++ b/src/displayapp/screens/settings/Settings.h @@ -43,10 +43,12 @@ namespace Pinetime { {Symbols::batteryHalf, "Battery", Apps::BatteryInfo}, {Symbols::clock, "Chimes", Apps::SettingChimes}, + {Symbols::none, "Chime strength", Apps::SettingChimeVibration}, + {Symbols::none, "Notif. str.", Apps::SettingNotifVibration}, {Symbols::tachometer, "Shake Calib.", Apps::SettingShakeThreshold}, + {Symbols::check, "Firmware", Apps::FirmwareValidation}, {Symbols::bluetooth, "Bluetooth", Apps::SettingBluetooth}, - {Symbols::list, "About", Apps::SysInfo}, // {Symbols::none, "None", Apps::None}, From 93f1002442c90c7f52794dc781ab1da5a1d3cec3 Mon Sep 17 00:00:00 2001 From: Julian Vos Date: Mon, 5 Aug 2024 22:22:25 +0200 Subject: [PATCH 03/11] feat: add json style watchface --- src/CMakeLists.txt | 1 + src/displayapp/UserApps.h | 1 + src/displayapp/apps/Apps.h.in | 1 + src/displayapp/apps/CMakeLists.txt | 1 + src/displayapp/fonts/CMakeLists.txt | 2 +- src/displayapp/fonts/fonts.json | 10 + src/displayapp/screens/WatchFaceJson.cpp | 225 +++++++++++++++++++++++ src/displayapp/screens/WatchFaceJson.h | 105 +++++++++++ src/libs/lv_conf.h | 3 +- 9 files changed, 347 insertions(+), 2 deletions(-) create mode 100644 src/displayapp/screens/WatchFaceJson.cpp create mode 100644 src/displayapp/screens/WatchFaceJson.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fd8ece62a6..b63ea4ce05 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -424,6 +424,7 @@ list(APPEND SOURCE_FILES displayapp/screens/WatchFaceDigital.cpp displayapp/screens/WatchFaceInfineat.cpp displayapp/screens/WatchFaceTerminal.cpp + displayapp/screens/WatchFaceJson.cpp displayapp/screens/WatchFacePineTimeStyle.cpp displayapp/screens/WatchFaceCasioStyleG7710.cpp diff --git a/src/displayapp/UserApps.h b/src/displayapp/UserApps.h index 67bbfa7d41..c1c52a4314 100644 --- a/src/displayapp/UserApps.h +++ b/src/displayapp/UserApps.h @@ -14,6 +14,7 @@ #include "displayapp/screens/WatchFaceInfineat.h" #include "displayapp/screens/WatchFacePineTimeStyle.h" #include "displayapp/screens/WatchFaceTerminal.h" +#include "displayapp/screens/WatchFaceJson.h" namespace Pinetime { namespace Applications { diff --git a/src/displayapp/apps/Apps.h.in b/src/displayapp/apps/Apps.h.in index 2104a267c0..dbcdd18777 100644 --- a/src/displayapp/apps/Apps.h.in +++ b/src/displayapp/apps/Apps.h.in @@ -50,6 +50,7 @@ namespace Pinetime { Analog, PineTimeStyle, Terminal, + Json, Infineat, CasioStyleG7710, }; diff --git a/src/displayapp/apps/CMakeLists.txt b/src/displayapp/apps/CMakeLists.txt index d78587609e..e92b5135e0 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -25,6 +25,7 @@ else() set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Analog") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::PineTimeStyle") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Terminal") + set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Json") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Infineat") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::CasioStyleG7710") set(WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}" CACHE STRING "List of watch faces to build into the firmware") diff --git a/src/displayapp/fonts/CMakeLists.txt b/src/displayapp/fonts/CMakeLists.txt index 22627efcad..242c136450 100644 --- a/src/displayapp/fonts/CMakeLists.txt +++ b/src/displayapp/fonts/CMakeLists.txt @@ -1,5 +1,5 @@ set(FONTS jetbrains_mono_42 jetbrains_mono_76 jetbrains_mono_bold_20 - jetbrains_mono_extrabold_compressed lv_font_sys_48 + jetbrains_mono_extrabold_compressed jetbrains_mono_16 lv_font_sys_48 open_sans_light fontawesome_weathericons) find_program(LV_FONT_CONV "lv_font_conv" NO_CACHE REQUIRED HINTS "${CMAKE_SOURCE_DIR}/node_modules/.bin") diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 41c383c0d4..6f5aaf34cb 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -14,6 +14,16 @@ "size": 20, "patches": ["jetbrains_mono_bold_20.c_zero.patch", "jetbrains_mono_bold_20.c_M.patch"] }, + "jetbrains_mono_16": { + "sources": [ + { + "file": "JetBrainsMono-Regular.ttf", + "range": "0x20-0x7e, 0x410-0x44f, 0xB0" + } + ], + "bpp": 1, + "size": 16 + }, "jetbrains_mono_42": { "sources": [ { diff --git a/src/displayapp/screens/WatchFaceJson.cpp b/src/displayapp/screens/WatchFaceJson.cpp new file mode 100644 index 0000000000..7ff5afea0c --- /dev/null +++ b/src/displayapp/screens/WatchFaceJson.cpp @@ -0,0 +1,225 @@ +#include +#include "displayapp/screens/WatchFaceJson.h" +#include "displayapp/screens/BatteryIcon.h" +#include "displayapp/screens/NotificationIcon.h" +#include "displayapp/screens/Symbols.h" +#include "displayapp/screens/WeatherSymbols.h" +#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 "components/ble/SimpleWeatherService.h" + +#define PROP_OFFSET 12 +#define LINE_HEIGHT 20 + +using namespace Pinetime::Applications::Screens; + +WatchFaceJson::WatchFaceJson(Controllers::DateTime& dateTimeController, + const Controllers::Battery& batteryController, + const Controllers::Ble& bleController, + Controllers::NotificationManager& notificationManager, + Controllers::Settings& settingsController, + Controllers::HeartRateController& heartRateController, + Controllers::MotionController& motionController, + Controllers::SimpleWeatherService& weatherService) + : currentDateTime {{}}, + dateTimeController {dateTimeController}, + batteryController {batteryController}, + bleController {bleController}, + notificationManager {notificationManager}, + settingsController {settingsController}, + heartRateController {heartRateController}, + motionController {motionController}, + weatherService {weatherService} { + lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x30, 0x38, 0x45)); + + notification_icon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(notification_icon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0); + + + label_open = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_open, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 0); + lv_obj_set_style_local_text_font(label_open, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_open, true); + lv_label_set_text_static(label_open, "#A6B2C0 {#"); + + label_time = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT); + lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_time, true); + lv_label_set_text_static(label_time, "#C792EA \"time\"##A6B2C0 :##92D69E \"12:34\"##A6B2C0 ,#"); + + label_date = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*2); + lv_obj_set_style_local_text_font(label_date, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_date, true); + lv_label_set_text_static(label_date, "#C792EA \"date\"##A6B2C0 :##92D69E \"1970-01-01\"##A6B2C0 ,#"); + + label_battery_open = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_battery_open, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*3); + lv_obj_set_style_local_text_font(label_battery_open, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_battery_open, true); + lv_label_set_text_static(label_battery_open, "#C792EA \"battery\"##A6B2C0 : {#"); + + label_battery_percent = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_battery_percent, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, (PROP_OFFSET*2), LINE_HEIGHT*4); + lv_obj_set_style_local_text_font(label_battery_percent, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_battery_percent, true); + lv_label_set_text_static(label_battery_percent, "#C792EA \"percent\"##A6B2C0 :##D19A66 0.69##A6B2C0 ,#"); + + label_battery_status = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_battery_status, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, (PROP_OFFSET*2), LINE_HEIGHT*5); + lv_obj_set_style_local_text_font(label_battery_status, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_battery_status, true); + lv_label_set_text_static(label_battery_status, "#C792EA \"state\"##A6B2C0 :##92D69E \"discharging\"#"); + + label_battery_close = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_battery_close, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*6); + lv_obj_set_style_local_text_font(label_battery_close, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_battery_close, true); + lv_label_set_text_static(label_battery_close, "#A6B2C0 },#"); + + label_steps = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_steps, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*7); + lv_obj_set_style_local_text_font(label_steps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_steps, true); + lv_label_set_text_static(label_steps, "#C792EA \"steps\"##A6B2C0 :##D19A66 0##A6B2C0 ,#"); + + label_status = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_status, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*8); + lv_obj_set_style_local_text_font(label_status, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_status, true); + lv_label_set_text_static(label_status, "#C792EA \"ble\"##A6B2C0 :##92D69E \"connected\"##A6B2C0 ,#"); + + label_weather = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_weather, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*9); + lv_obj_set_style_local_text_font(label_weather, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_weather, true); + lv_label_set_text_static(label_weather, "#C792EA \"weather\"##A6B2C0 :##92D69E \" \"##A6B2C0 ,#"); + + weather_icon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_font(weather_icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &fontawesome_weathericons); + lv_obj_set_style_local_text_color(weather_icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x92, 0xD6, 0x9E)); + lv_label_set_text(weather_icon, Symbols::ban); + lv_obj_align(weather_icon, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 133, (LINE_HEIGHT*9)-3); + + lv_obj_set_auto_realign(weather_icon, true); + + label_temperature = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_temperature, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*10); + lv_obj_set_style_local_text_font(label_temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_temperature, true); + lv_label_set_text_static(label_temperature, "#C792EA \"temperature\"##A6B2C0 :##D19A66 -20#"); + + label_close = lv_label_create(lv_scr_act(), nullptr); + lv_obj_align(label_close, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, LINE_HEIGHT*11); + lv_obj_set_style_local_text_font(label_close, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); + lv_label_set_recolor(label_close, true); + lv_label_set_text_static(label_close, "#A6B2C0 }#"); + + taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); + Refresh(); +} + +WatchFaceJson::~WatchFaceJson() { + lv_task_del(taskRefresh); + lv_obj_clean(lv_scr_act()); +} + +void WatchFaceJson::Refresh() { + currentWeather = weatherService.Current(); + + if (currentWeather.IsUpdated()) { + auto optCurrentWeather = currentWeather.Get(); + + if (optCurrentWeather) { + int16_t temp = optCurrentWeather->temperature; + + if (settingsController.GetWeatherFormat() == Controllers::Settings::WeatherFormat::Imperial) { + temp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(temp); + } + + temp = temp / 100 + (temp % 100 >= 50 ? 1 : 0); + + lv_label_set_text(weather_icon, Symbols::GetSymbol(optCurrentWeather->iconId)); + lv_label_set_text_fmt(label_temperature, "#C792EA \"temperature\"##A6B2C0 :##D19A66 %d#", temp); + } else { + lv_label_set_text(weather_icon, Symbols::ban); + lv_label_set_text_static(label_temperature, "#C792EA \"temperature\"##A6B2C0 :##D19A66 null#"); + } + + lv_obj_realign(weather_icon); + } + + powerPresent = batteryController.IsPowerPresent(); + batteryPercentRemaining = batteryController.PercentRemaining(); + if (batteryPercentRemaining.IsUpdated() || powerPresent.IsUpdated()) { + lv_label_set_text_fmt(label_battery_percent, "#C792EA \"percent\"##A6B2C0 :##D19A66 %.2f##A6B2C0 ,#", (batteryPercentRemaining.Get()/100)); + if (batteryController.IsPowerPresent()) { + lv_label_set_text_static(label_battery_status, "#C792EA \"state\"##A6B2C0 :##92D69E \"charging\"#"); + } else { + lv_label_set_text_static(label_battery_status, "#C792EA \"state\"##A6B2C0 :##92D69E \"discharging\"#"); + } + } + + bleState = bleController.IsConnected(); + bleRadioEnabled = bleController.IsRadioEnabled(); + if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { + if (!bleRadioEnabled.Get()) { + lv_label_set_text_static(label_status, "#C792EA \"ble\"##A6B2C0 :##92D69E \"disabled\"##A6B2C0 ,#"); + } else { + if (bleState.Get()) { + lv_label_set_text_static(label_status, "#C792EA \"ble\"##A6B2C0 :##92D69E \"connected\"##A6B2C0 ,#"); + } else { + lv_label_set_text_static(label_status, "#C792EA \"ble\"##A6B2C0 :##92D69E \"disconnected\"##A6B2C0 ,#"); + } + } + } + + notificationState = notificationManager.AreNewNotificationsAvailable(); + if (notificationState.IsUpdated()) { + if (notificationState.Get()) { + lv_label_set_text_static(notification_icon, NotificationIcon::GetIcon(notificationState.Get())); + } else { + lv_label_set_text_static(notification_icon, ""); + } + } + + currentDateTime = std::chrono::time_point_cast(dateTimeController.CurrentDateTime()); + if (currentDateTime.IsUpdated()) { + uint8_t hour = dateTimeController.Hours(); + uint8_t minute = dateTimeController.Minutes(); + uint8_t second = dateTimeController.Seconds(); + + if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { + char ampmChar[3] = "AM"; + if (hour == 0) { + hour = 12; + } else if (hour == 12) { + ampmChar[0] = 'P'; + } else if (hour > 12) { + hour = hour - 12; + ampmChar[0] = 'P'; + } + lv_label_set_text_fmt(label_time, "#C792EA \"time\"##A6B2C0 :##92D69E \"%02d:%02d:%02d %s\"##A6B2C0 ,#", hour, minute, second, ampmChar); + } else { + lv_label_set_text_fmt(label_time, "#C792EA \"time\"##A6B2C0 :##92D69E \"%02d:%02d:%02d\"##A6B2C0 ,#", hour, minute, second); + } + + currentDate = std::chrono::time_point_cast(currentDateTime.Get()); + if (currentDate.IsUpdated()) { + uint16_t year = dateTimeController.Year(); + Controllers::DateTime::Months month = dateTimeController.Month(); + uint8_t day = dateTimeController.Day(); + lv_label_set_text_fmt(label_date, "#C792EA \"date\"##A6B2C0 :##92D69E \"%04d-%02d-%02d\"##A6B2C0 ,#", short(year), char(month), char(day)); + } + } + + stepCount = motionController.NbSteps(); + if (stepCount.IsUpdated()) { + lv_label_set_text_fmt(label_steps, "#C792EA \"steps\"##A6B2C0 :##D19A66 %lu##A6B2C0 ,#", stepCount.Get()); + } +} diff --git a/src/displayapp/screens/WatchFaceJson.h b/src/displayapp/screens/WatchFaceJson.h new file mode 100644 index 0000000000..b473a58093 --- /dev/null +++ b/src/displayapp/screens/WatchFaceJson.h @@ -0,0 +1,105 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "displayapp/screens/Screen.h" +#include "components/datetime/DateTimeController.h" +#include "components/ble/SimpleWeatherService.h" +#include "utility/DirtyValue.h" + +namespace Pinetime { + namespace Controllers { + class Settings; + class Battery; + class Ble; + class NotificationManager; + class HeartRateController; + class MotionController; + } + + namespace Applications { + namespace Screens { + + class WatchFaceJson : public Screen { + public: + WatchFaceJson(Controllers::DateTime& dateTimeController, + const Controllers::Battery& batteryController, + const Controllers::Ble& bleController, + Controllers::NotificationManager& notificationManager, + Controllers::Settings& settingsController, + Controllers::HeartRateController& heartRateController, + Controllers::MotionController& motionController, + Controllers::SimpleWeatherService& weather); + ~WatchFaceJson() override; + + void Refresh() override; + + private: + Utility::DirtyValue batteryPercentRemaining {}; + Utility::DirtyValue powerPresent {}; + Utility::DirtyValue bleState {}; + Utility::DirtyValue bleRadioEnabled {}; + Utility::DirtyValue> currentDateTime {}; + Utility::DirtyValue stepCount {}; + Utility::DirtyValue heartbeat {}; + Utility::DirtyValue heartbeatRunning {}; + Utility::DirtyValue notificationState {}; + Utility::DirtyValue> currentDate; + Utility::DirtyValue> currentWeather {}; + + lv_obj_t* notification_icon; + + lv_obj_t* label_open; + lv_obj_t* label_close; + + lv_obj_t* label_time; + lv_obj_t* label_date; + lv_obj_t* label_battery_open; + lv_obj_t* label_battery_close; + lv_obj_t* label_battery_percent; + lv_obj_t* label_battery_status; + lv_obj_t* label_steps; + lv_obj_t* label_heartrate; + lv_obj_t* label_status; + lv_obj_t* label_weather; + lv_obj_t* weather_icon; + lv_obj_t* label_temperature; + + Controllers::DateTime& dateTimeController; + const Controllers::Battery& batteryController; + const Controllers::Ble& bleController; + Controllers::NotificationManager& notificationManager; + Controllers::Settings& settingsController; + Controllers::HeartRateController& heartRateController; + Controllers::MotionController& motionController; + Controllers::SimpleWeatherService& weatherService; + + lv_task_t* taskRefresh; + }; + } + + template <> + struct WatchFaceTraits { + static constexpr WatchFace watchFace = WatchFace::Json; + static constexpr const char* name = "Json"; + + static Screens::Screen* Create(AppControllers& controllers) { + return new Screens::WatchFaceJson(controllers.dateTimeController, + controllers.batteryController, + controllers.bleController, + controllers.notificationManager, + controllers.settingsController, + controllers.heartRateController, + controllers.motionController, + *controllers.weatherController); + }; + + static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) { + return true; + } + }; + } +} diff --git a/src/libs/lv_conf.h b/src/libs/lv_conf.h index c23647f2c0..e01c07d00e 100644 --- a/src/libs/lv_conf.h +++ b/src/libs/lv_conf.h @@ -415,6 +415,7 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(jetbrains_mono_bold_20) \ LV_FONT_DECLARE(jetbrains_mono_extrabold_compressed) \ + LV_FONT_DECLARE(jetbrains_mono_16) \ LV_FONT_DECLARE(jetbrains_mono_42) \ LV_FONT_DECLARE(jetbrains_mono_76) \ LV_FONT_DECLARE(open_sans_light) \ @@ -538,7 +539,7 @@ typedef void* lv_font_user_data_t; #define lv_snprintf snprintf #define lv_vsnprintf vsnprintf #else /*!LV_SPRINTF_CUSTOM*/ -#define LV_SPRINTF_DISABLE_FLOAT 1 +#define LV_SPRINTF_DISABLE_FLOAT 0 #endif /*LV_SPRINTF_CUSTOM*/ /*=================== From 279bf77fdd85ec35410cc3fa3ff2a37d5babf378 Mon Sep 17 00:00:00 2001 From: Julian Vos Date: Wed, 28 Aug 2024 09:39:10 +0200 Subject: [PATCH 04/11] chore: also run workflows on my branch --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c24e23748f..e6128721ec 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,12 +3,12 @@ name: CI # Run this workflow whenever the build may be affected on: push: - branches: [ main ] + branches: [ main, ghoelian ] paths-ignore: - 'doc/**' - '**.md' pull_request: - branches: [ main ] + branches: [ main, ghoelian ] paths-ignore: - 'doc/**' - '**.md' From 950ac015dfba52f5b24900a5b794271189fadf8c Mon Sep 17 00:00:00 2001 From: Julian Vos Date: Wed, 28 Aug 2024 09:39:37 +0200 Subject: [PATCH 05/11] feat: don't wake screen on chime --- src/displayapp/DisplayApp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 83bb739052..9f3af9d929 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -376,7 +376,6 @@ void DisplayApp::Refresh() { // What should happen here? break; case Messages::Chime: - LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::None); motorController.RunForDuration(static_cast(settingsController.GetChimeVibration())); break; case Messages::OnChargingEvent: From 41d2ccdaa840fc0bcff6efee928787b686b4ff90 Mon Sep 17 00:00:00 2001 From: Julian Vos Date: Wed, 28 Aug 2024 13:03:56 +0200 Subject: [PATCH 06/11] Revert "feat: don't wake screen on chime" This reverts commit 950ac015dfba52f5b24900a5b794271189fadf8c. --- src/displayapp/DisplayApp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 9f3af9d929..83bb739052 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -376,6 +376,7 @@ void DisplayApp::Refresh() { // What should happen here? break; case Messages::Chime: + LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::None); motorController.RunForDuration(static_cast(settingsController.GetChimeVibration())); break; case Messages::OnChargingEvent: From b691d8df33de6dcb2830c2086afbe5463c981edf Mon Sep 17 00:00:00 2001 From: Julian Vos Date: Thu, 21 Nov 2024 20:09:26 +0000 Subject: [PATCH 07/11] chore: remove json watchface don't have the space for the fonts lmao --- src/CMakeLists.txt | 1 - src/displayapp/UserApps.h | 1 - src/displayapp/screens/WatchFaceJson.cpp | 225 ----------------------- src/displayapp/screens/WatchFaceJson.h | 105 ----------- 4 files changed, 332 deletions(-) delete mode 100644 src/displayapp/screens/WatchFaceJson.cpp delete mode 100644 src/displayapp/screens/WatchFaceJson.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 62e658806c..bc6990cf84 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -426,7 +426,6 @@ list(APPEND SOURCE_FILES displayapp/screens/WatchFaceDigital.cpp displayapp/screens/WatchFaceInfineat.cpp displayapp/screens/WatchFaceTerminal.cpp - displayapp/screens/WatchFaceJson.cpp displayapp/screens/WatchFacePineTimeStyle.cpp displayapp/screens/WatchFaceCasioStyleG7710.cpp diff --git a/src/displayapp/UserApps.h b/src/displayapp/UserApps.h index c1c52a4314..67bbfa7d41 100644 --- a/src/displayapp/UserApps.h +++ b/src/displayapp/UserApps.h @@ -14,7 +14,6 @@ #include "displayapp/screens/WatchFaceInfineat.h" #include "displayapp/screens/WatchFacePineTimeStyle.h" #include "displayapp/screens/WatchFaceTerminal.h" -#include "displayapp/screens/WatchFaceJson.h" namespace Pinetime { namespace Applications { diff --git a/src/displayapp/screens/WatchFaceJson.cpp b/src/displayapp/screens/WatchFaceJson.cpp deleted file mode 100644 index 7ff5afea0c..0000000000 --- a/src/displayapp/screens/WatchFaceJson.cpp +++ /dev/null @@ -1,225 +0,0 @@ -#include -#include "displayapp/screens/WatchFaceJson.h" -#include "displayapp/screens/BatteryIcon.h" -#include "displayapp/screens/NotificationIcon.h" -#include "displayapp/screens/Symbols.h" -#include "displayapp/screens/WeatherSymbols.h" -#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 "components/ble/SimpleWeatherService.h" - -#define PROP_OFFSET 12 -#define LINE_HEIGHT 20 - -using namespace Pinetime::Applications::Screens; - -WatchFaceJson::WatchFaceJson(Controllers::DateTime& dateTimeController, - const Controllers::Battery& batteryController, - const Controllers::Ble& bleController, - Controllers::NotificationManager& notificationManager, - Controllers::Settings& settingsController, - Controllers::HeartRateController& heartRateController, - Controllers::MotionController& motionController, - Controllers::SimpleWeatherService& weatherService) - : currentDateTime {{}}, - dateTimeController {dateTimeController}, - batteryController {batteryController}, - bleController {bleController}, - notificationManager {notificationManager}, - settingsController {settingsController}, - heartRateController {heartRateController}, - motionController {motionController}, - weatherService {weatherService} { - lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x30, 0x38, 0x45)); - - notification_icon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(notification_icon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0); - - - label_open = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_open, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 0); - lv_obj_set_style_local_text_font(label_open, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_open, true); - lv_label_set_text_static(label_open, "#A6B2C0 {#"); - - label_time = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT); - lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_time, true); - lv_label_set_text_static(label_time, "#C792EA \"time\"##A6B2C0 :##92D69E \"12:34\"##A6B2C0 ,#"); - - label_date = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*2); - lv_obj_set_style_local_text_font(label_date, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_date, true); - lv_label_set_text_static(label_date, "#C792EA \"date\"##A6B2C0 :##92D69E \"1970-01-01\"##A6B2C0 ,#"); - - label_battery_open = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_battery_open, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*3); - lv_obj_set_style_local_text_font(label_battery_open, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_battery_open, true); - lv_label_set_text_static(label_battery_open, "#C792EA \"battery\"##A6B2C0 : {#"); - - label_battery_percent = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_battery_percent, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, (PROP_OFFSET*2), LINE_HEIGHT*4); - lv_obj_set_style_local_text_font(label_battery_percent, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_battery_percent, true); - lv_label_set_text_static(label_battery_percent, "#C792EA \"percent\"##A6B2C0 :##D19A66 0.69##A6B2C0 ,#"); - - label_battery_status = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_battery_status, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, (PROP_OFFSET*2), LINE_HEIGHT*5); - lv_obj_set_style_local_text_font(label_battery_status, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_battery_status, true); - lv_label_set_text_static(label_battery_status, "#C792EA \"state\"##A6B2C0 :##92D69E \"discharging\"#"); - - label_battery_close = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_battery_close, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*6); - lv_obj_set_style_local_text_font(label_battery_close, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_battery_close, true); - lv_label_set_text_static(label_battery_close, "#A6B2C0 },#"); - - label_steps = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_steps, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*7); - lv_obj_set_style_local_text_font(label_steps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_steps, true); - lv_label_set_text_static(label_steps, "#C792EA \"steps\"##A6B2C0 :##D19A66 0##A6B2C0 ,#"); - - label_status = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_status, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*8); - lv_obj_set_style_local_text_font(label_status, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_status, true); - lv_label_set_text_static(label_status, "#C792EA \"ble\"##A6B2C0 :##92D69E \"connected\"##A6B2C0 ,#"); - - label_weather = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_weather, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*9); - lv_obj_set_style_local_text_font(label_weather, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_weather, true); - lv_label_set_text_static(label_weather, "#C792EA \"weather\"##A6B2C0 :##92D69E \" \"##A6B2C0 ,#"); - - weather_icon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(weather_icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &fontawesome_weathericons); - lv_obj_set_style_local_text_color(weather_icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_MAKE(0x92, 0xD6, 0x9E)); - lv_label_set_text(weather_icon, Symbols::ban); - lv_obj_align(weather_icon, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 133, (LINE_HEIGHT*9)-3); - - lv_obj_set_auto_realign(weather_icon, true); - - label_temperature = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_temperature, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, PROP_OFFSET, LINE_HEIGHT*10); - lv_obj_set_style_local_text_font(label_temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_temperature, true); - lv_label_set_text_static(label_temperature, "#C792EA \"temperature\"##A6B2C0 :##D19A66 -20#"); - - label_close = lv_label_create(lv_scr_act(), nullptr); - lv_obj_align(label_close, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, LINE_HEIGHT*11); - lv_obj_set_style_local_text_font(label_close, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_16); - lv_label_set_recolor(label_close, true); - lv_label_set_text_static(label_close, "#A6B2C0 }#"); - - taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); - Refresh(); -} - -WatchFaceJson::~WatchFaceJson() { - lv_task_del(taskRefresh); - lv_obj_clean(lv_scr_act()); -} - -void WatchFaceJson::Refresh() { - currentWeather = weatherService.Current(); - - if (currentWeather.IsUpdated()) { - auto optCurrentWeather = currentWeather.Get(); - - if (optCurrentWeather) { - int16_t temp = optCurrentWeather->temperature; - - if (settingsController.GetWeatherFormat() == Controllers::Settings::WeatherFormat::Imperial) { - temp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(temp); - } - - temp = temp / 100 + (temp % 100 >= 50 ? 1 : 0); - - lv_label_set_text(weather_icon, Symbols::GetSymbol(optCurrentWeather->iconId)); - lv_label_set_text_fmt(label_temperature, "#C792EA \"temperature\"##A6B2C0 :##D19A66 %d#", temp); - } else { - lv_label_set_text(weather_icon, Symbols::ban); - lv_label_set_text_static(label_temperature, "#C792EA \"temperature\"##A6B2C0 :##D19A66 null#"); - } - - lv_obj_realign(weather_icon); - } - - powerPresent = batteryController.IsPowerPresent(); - batteryPercentRemaining = batteryController.PercentRemaining(); - if (batteryPercentRemaining.IsUpdated() || powerPresent.IsUpdated()) { - lv_label_set_text_fmt(label_battery_percent, "#C792EA \"percent\"##A6B2C0 :##D19A66 %.2f##A6B2C0 ,#", (batteryPercentRemaining.Get()/100)); - if (batteryController.IsPowerPresent()) { - lv_label_set_text_static(label_battery_status, "#C792EA \"state\"##A6B2C0 :##92D69E \"charging\"#"); - } else { - lv_label_set_text_static(label_battery_status, "#C792EA \"state\"##A6B2C0 :##92D69E \"discharging\"#"); - } - } - - bleState = bleController.IsConnected(); - bleRadioEnabled = bleController.IsRadioEnabled(); - if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { - if (!bleRadioEnabled.Get()) { - lv_label_set_text_static(label_status, "#C792EA \"ble\"##A6B2C0 :##92D69E \"disabled\"##A6B2C0 ,#"); - } else { - if (bleState.Get()) { - lv_label_set_text_static(label_status, "#C792EA \"ble\"##A6B2C0 :##92D69E \"connected\"##A6B2C0 ,#"); - } else { - lv_label_set_text_static(label_status, "#C792EA \"ble\"##A6B2C0 :##92D69E \"disconnected\"##A6B2C0 ,#"); - } - } - } - - notificationState = notificationManager.AreNewNotificationsAvailable(); - if (notificationState.IsUpdated()) { - if (notificationState.Get()) { - lv_label_set_text_static(notification_icon, NotificationIcon::GetIcon(notificationState.Get())); - } else { - lv_label_set_text_static(notification_icon, ""); - } - } - - currentDateTime = std::chrono::time_point_cast(dateTimeController.CurrentDateTime()); - if (currentDateTime.IsUpdated()) { - uint8_t hour = dateTimeController.Hours(); - uint8_t minute = dateTimeController.Minutes(); - uint8_t second = dateTimeController.Seconds(); - - if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { - char ampmChar[3] = "AM"; - if (hour == 0) { - hour = 12; - } else if (hour == 12) { - ampmChar[0] = 'P'; - } else if (hour > 12) { - hour = hour - 12; - ampmChar[0] = 'P'; - } - lv_label_set_text_fmt(label_time, "#C792EA \"time\"##A6B2C0 :##92D69E \"%02d:%02d:%02d %s\"##A6B2C0 ,#", hour, minute, second, ampmChar); - } else { - lv_label_set_text_fmt(label_time, "#C792EA \"time\"##A6B2C0 :##92D69E \"%02d:%02d:%02d\"##A6B2C0 ,#", hour, minute, second); - } - - currentDate = std::chrono::time_point_cast(currentDateTime.Get()); - if (currentDate.IsUpdated()) { - uint16_t year = dateTimeController.Year(); - Controllers::DateTime::Months month = dateTimeController.Month(); - uint8_t day = dateTimeController.Day(); - lv_label_set_text_fmt(label_date, "#C792EA \"date\"##A6B2C0 :##92D69E \"%04d-%02d-%02d\"##A6B2C0 ,#", short(year), char(month), char(day)); - } - } - - stepCount = motionController.NbSteps(); - if (stepCount.IsUpdated()) { - lv_label_set_text_fmt(label_steps, "#C792EA \"steps\"##A6B2C0 :##D19A66 %lu##A6B2C0 ,#", stepCount.Get()); - } -} diff --git a/src/displayapp/screens/WatchFaceJson.h b/src/displayapp/screens/WatchFaceJson.h deleted file mode 100644 index b473a58093..0000000000 --- a/src/displayapp/screens/WatchFaceJson.h +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include "displayapp/screens/Screen.h" -#include "components/datetime/DateTimeController.h" -#include "components/ble/SimpleWeatherService.h" -#include "utility/DirtyValue.h" - -namespace Pinetime { - namespace Controllers { - class Settings; - class Battery; - class Ble; - class NotificationManager; - class HeartRateController; - class MotionController; - } - - namespace Applications { - namespace Screens { - - class WatchFaceJson : public Screen { - public: - WatchFaceJson(Controllers::DateTime& dateTimeController, - const Controllers::Battery& batteryController, - const Controllers::Ble& bleController, - Controllers::NotificationManager& notificationManager, - Controllers::Settings& settingsController, - Controllers::HeartRateController& heartRateController, - Controllers::MotionController& motionController, - Controllers::SimpleWeatherService& weather); - ~WatchFaceJson() override; - - void Refresh() override; - - private: - Utility::DirtyValue batteryPercentRemaining {}; - Utility::DirtyValue powerPresent {}; - Utility::DirtyValue bleState {}; - Utility::DirtyValue bleRadioEnabled {}; - Utility::DirtyValue> currentDateTime {}; - Utility::DirtyValue stepCount {}; - Utility::DirtyValue heartbeat {}; - Utility::DirtyValue heartbeatRunning {}; - Utility::DirtyValue notificationState {}; - Utility::DirtyValue> currentDate; - Utility::DirtyValue> currentWeather {}; - - lv_obj_t* notification_icon; - - lv_obj_t* label_open; - lv_obj_t* label_close; - - lv_obj_t* label_time; - lv_obj_t* label_date; - lv_obj_t* label_battery_open; - lv_obj_t* label_battery_close; - lv_obj_t* label_battery_percent; - lv_obj_t* label_battery_status; - lv_obj_t* label_steps; - lv_obj_t* label_heartrate; - lv_obj_t* label_status; - lv_obj_t* label_weather; - lv_obj_t* weather_icon; - lv_obj_t* label_temperature; - - Controllers::DateTime& dateTimeController; - const Controllers::Battery& batteryController; - const Controllers::Ble& bleController; - Controllers::NotificationManager& notificationManager; - Controllers::Settings& settingsController; - Controllers::HeartRateController& heartRateController; - Controllers::MotionController& motionController; - Controllers::SimpleWeatherService& weatherService; - - lv_task_t* taskRefresh; - }; - } - - template <> - struct WatchFaceTraits { - static constexpr WatchFace watchFace = WatchFace::Json; - static constexpr const char* name = "Json"; - - static Screens::Screen* Create(AppControllers& controllers) { - return new Screens::WatchFaceJson(controllers.dateTimeController, - controllers.batteryController, - controllers.bleController, - controllers.notificationManager, - controllers.settingsController, - controllers.heartRateController, - controllers.motionController, - *controllers.weatherController); - }; - - static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) { - return true; - } - }; - } -} From 884a5081a87cc8a2795c7f7508c7c2a3c99db2c5 Mon Sep 17 00:00:00 2001 From: Julian Vos Date: Thu, 21 Nov 2024 20:46:19 +0000 Subject: [PATCH 08/11] chore: add node packages --- package-lock.json | 119 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 5 ++ 2 files changed, 124 insertions(+) create mode 100644 package-lock.json create mode 100644 package.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..89da6e7b39 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,119 @@ +{ + "name": "InfiniTime", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "lv_font_conv": "^1.5.3" + } + }, + "node_modules/lv_font_conv": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/lv_font_conv/-/lv_font_conv-1.5.3.tgz", + "integrity": "sha512-0xJQThBOw2iptFccSXrKDIUTQAwr/2zhKjCI1lATIRgZo8uvYRTmenKafW9yTw6G0y5AyW00tqGpUtYuTuBIbQ==", + "bundleDependencies": [ + "argparse", + "bit-buffer", + "debug", + "make-error", + "mkdirp", + "opentype.js", + "pngjs" + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.0", + "bit-buffer": "^0.2.5", + "debug": "^4.3.3", + "make-error": "^1.3.5", + "mkdirp": "^1.0.4", + "opentype.js": "^1.3.4", + "pngjs": "^6.0.0" + }, + "bin": { + "lv_font_conv": "lv_font_conv.js" + } + }, + "node_modules/lv_font_conv/node_modules/argparse": { + "version": "2.0.1", + "inBundle": true, + "license": "Python-2.0" + }, + "node_modules/lv_font_conv/node_modules/bit-buffer": { + "version": "0.2.5", + "inBundle": true, + "license": "MIT" + }, + "node_modules/lv_font_conv/node_modules/debug": { + "version": "4.3.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/lv_font_conv/node_modules/make-error": { + "version": "1.3.6", + "inBundle": true, + "license": "ISC" + }, + "node_modules/lv_font_conv/node_modules/mkdirp": { + "version": "1.0.4", + "inBundle": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lv_font_conv/node_modules/ms": { + "version": "2.1.2", + "inBundle": true, + "license": "MIT" + }, + "node_modules/lv_font_conv/node_modules/opentype.js": { + "version": "1.3.4", + "inBundle": true, + "license": "MIT", + "dependencies": { + "string.prototype.codepointat": "^0.2.1", + "tiny-inflate": "^1.0.3" + }, + "bin": { + "ot": "bin/ot" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/lv_font_conv/node_modules/pngjs": { + "version": "6.0.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/lv_font_conv/node_modules/string.prototype.codepointat": { + "version": "0.2.1", + "inBundle": true, + "license": "MIT" + }, + "node_modules/lv_font_conv/node_modules/tiny-inflate": { + "version": "1.0.3", + "inBundle": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000..f0e20704e8 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "lv_font_conv": "^1.5.3" + } +} From 569c3a23161c54986c2947c42707f52686e58707 Mon Sep 17 00:00:00 2001 From: Julian Vos Date: Thu, 21 Nov 2024 20:46:31 +0000 Subject: [PATCH 09/11] chore: add build.sh --- build.sh | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100755 build.sh diff --git a/build.sh b/build.sh new file mode 100755 index 0000000000..09fd0b9f83 --- /dev/null +++ b/build.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +mkdir -p build +cd build + +echo "Configuring build..." +cmake -DARM_NONE_EABI_TOOLCHAIN_PATH="/workspaces/infinitime/gcc-arm" -DNRF5_SDK_PATH="/workspaces/infinitime/nRF5_SDK" -DCMAKE_BUILD_TYPE="Release" -DBUILD_DFU=1 -DBUILD_RESOURCES=1 -DTARGET_DEVICE="PINETIME" .. +echo "Finished configuring build" + +echo "Building..." +make -j4 pinetime-mcuboot-app +echo "Finished building" From e75735b0c7b96a02d5b755000ef0656062a1677c Mon Sep 17 00:00:00 2001 From: Julian Vos Date: Thu, 21 Nov 2024 20:46:48 +0000 Subject: [PATCH 10/11] chore: remove json watchface --- src/displayapp/apps/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/displayapp/apps/CMakeLists.txt b/src/displayapp/apps/CMakeLists.txt index e92b5135e0..d78587609e 100644 --- a/src/displayapp/apps/CMakeLists.txt +++ b/src/displayapp/apps/CMakeLists.txt @@ -25,7 +25,6 @@ else() set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Analog") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::PineTimeStyle") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Terminal") - set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Json") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Infineat") set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::CasioStyleG7710") set(WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}" CACHE STRING "List of watch faces to build into the firmware") From d38b4350bfeb3701b9ea0892541d1262754837c5 Mon Sep 17 00:00:00 2001 From: Julian Vos Date: Thu, 21 Nov 2024 21:15:33 +0000 Subject: [PATCH 11/11] fix: remove temperature rounding --- src/displayapp/screens/WatchFaceCasioStyleG7710.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp index a4308660ec..85005d1757 100644 --- a/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp +++ b/src/displayapp/screens/WatchFaceCasioStyleG7710.cpp @@ -386,7 +386,6 @@ void WatchFaceCasioStyleG7710::Refresh() { tempUnit = 'F'; } - temp = temp / 100 + (temp % 100 >= 50 ? 1 : 0); lv_label_set_text_fmt(label_temperature, "%d°%c", temp, tempUnit); lv_label_set_text(weatherIcon, Symbols::GetSymbol(optCurrentWeather->iconId)); } else {