Author: Adam <git@apiote.xyz>
change world face to world hands and prepare weather
src/components/datetime/DateTimeController.h | 2 src/displayapp/screens/Clock.cpp | 3 src/displayapp/screens/WatchFaceMine.cpp | 155 +++++++++++++++++---- src/displayapp/screens/WatchFaceMine.h | 24 ++
diff --git a/src/components/datetime/DateTimeController.h b/src/components/datetime/DateTimeController.h index aa88a423dede4eea082c9e28c6790a0653ecc1e8..00e73dcc84c7f545e7c484e6fdfd53ab1aadb159 100644 --- a/src/components/datetime/DateTimeController.h +++ b/src/components/datetime/DateTimeController.h @@ -143,7 +143,7 @@ return currentDateTime - std::chrono::seconds((tzOffset + dstOffset) * 15 * 60); } std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> WorldDateTime(uint8_t index) const { - return UTCDateTime() + std::chrono::seconds(worldOffset(index) * 15 * 60); + return UTCDateTime() + std::chrono::seconds((worldOffset(index) + dstOffset) * 15 * 60); // pedantically, it should be dstOffset of the timezone at index, not main clock timezone } std::chrono::seconds Uptime() const { diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index 06372b8c56f05d3c5bea33c101b53eb1618f8c99..17b4f092af2898540a2f20fc50e23b3b51e9b226 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -130,5 +130,6 @@ batteryController, bleController, notificationManager, settingsController, - motionController); + motionController, + weatherService); } diff --git a/src/displayapp/screens/WatchFaceMine.cpp b/src/displayapp/screens/WatchFaceMine.cpp index 4ba5f82ab344c58a9c1345c1dda44c41ff30f256..8e038b408783feeb55edb5d96c7de3e2bada867e 100644 --- a/src/displayapp/screens/WatchFaceMine.cpp +++ b/src/displayapp/screens/WatchFaceMine.cpp @@ -7,6 +7,7 @@ #include "displayapp/screens/BleIcon.h" #include "displayapp/screens/Symbols.h" #include "displayapp/screens/NotificationIcon.h" #include "components/settings/Settings.h" +#include "components/ble/weather/WeatherService.h" #include "displayapp/InfiniTimeTheme.h" using namespace Pinetime::Applications::Screens; @@ -48,14 +49,16 @@ const Controllers::Battery& batteryController, const Controllers::Ble& bleController, Controllers::NotificationManager& notificationManager, Controllers::Settings& settingsController, - Controllers::MotionController& motionController) + Controllers::MotionController& motionController, + Controllers::WeatherService& weatherService) : currentDateTime {{}}, dateTimeController {dateTimeController}, batteryController {batteryController}, bleController {bleController}, notificationManager {notificationManager}, settingsController {settingsController}, - motionController {motionController} { + motionController {motionController}, + weatherService {weatherService} { sHour = 99; sMinute = 99; @@ -78,6 +81,18 @@ lv_obj_set_style_local_text_color(bluetoothIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x0082fc)); lv_label_set_text_static(bluetoothIcon, BleIcon::GetIcon(false)); lv_obj_align(bluetoothIcon, NULL, LV_ALIGN_IN_TOP_RIGHT, -30, 0); + weatherIcon = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(weatherIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x7b7e82)); + lv_obj_set_style_local_text_font(weatherIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &fontawesome_weathericons); + lv_label_set_text(weatherIcon, ""); + lv_obj_align(weatherIcon, nullptr, LV_ALIGN_IN_TOP_MID, -15, 50); + lv_obj_set_auto_realign(weatherIcon, true); + + temperature = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_text(temperature, ""); + lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x7b7e82)); + lv_obj_align(temperature, nullptr, LV_ALIGN_IN_TOP_MID, 15, 50); + lv_style_init(&tick_style); lv_style_set_line_width(&tick_style, LV_STATE_DEFAULT, 5); @@ -94,28 +109,18 @@ lv_style_set_line_rounded(&tick_style_six, LV_STATE_DEFAULT, true); for (int i = 0; i < 24; ++i) { tick[i] = lv_line_create(lv_scr_act(), NULL); - tick_world[i] = lv_line_create(lv_scr_act(), NULL); if (i == 0) { lv_obj_add_style(tick[i], LV_LINE_PART_MAIN, &tick_style_zero); - lv_obj_add_style(tick_world[i], LV_LINE_PART_MAIN, &tick_style_zero); } else if (i%3 == 0) { lv_obj_add_style(tick[i], LV_LINE_PART_MAIN, &tick_style_six); - lv_obj_add_style(tick_world[i], LV_LINE_PART_MAIN, &tick_style_six); } else { lv_obj_add_style(tick[i], LV_LINE_PART_MAIN, &tick_style); - lv_obj_add_style(tick_world[i], LV_LINE_PART_MAIN, &tick_style); } } clockType = settingsController.GetClockType(); DrawFace(); - if (dateTimeController.isWorldTimeEnabled(0)) { - worldClockOffset = dateTimeController.worldOffset(0); - DrawOffsetFace(); - } - - label_date_greg = lv_label_create(lv_scr_act(), NULL); lv_obj_set_style_local_text_color(label_date_greg, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x919191)); lv_label_set_text_fmt(label_date_greg, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), dateTimeController.Day()); @@ -129,7 +134,9 @@ lv_label_set_align(label_date_world, LV_LABEL_ALIGN_CENTER); lv_obj_align(label_date_world, NULL, LV_ALIGN_CENTER, -50, 0); + minute_body_world = lv_line_create(lv_scr_act(), NULL); minute_body = lv_line_create(lv_scr_act(), NULL); + hour_body_world = lv_line_create(lv_scr_act(), NULL); hour_body = lv_line_create(lv_scr_act(), NULL); second_body = lv_line_create(lv_scr_act(), NULL); @@ -142,12 +149,24 @@ lv_style_set_line_color(&second_line_style, LV_STATE_DEFAULT, lv_color_hex(0xff5c57)); lv_style_set_line_rounded(&second_line_style, LV_STATE_DEFAULT, true); lv_obj_add_style(second_body, LV_LINE_PART_MAIN, &second_line_style); + lv_style_init(&minute_line_style_world); + lv_style_set_line_width(&minute_line_style_world, LV_STATE_DEFAULT, 5); + lv_style_set_line_color(&minute_line_style_world, LV_STATE_DEFAULT, lv_color_hex(0x5d3636)); + lv_style_set_line_rounded(&minute_line_style_world, LV_STATE_DEFAULT, true); + lv_obj_add_style(minute_body_world, LV_LINE_PART_MAIN, &minute_line_style_world); + lv_style_init(&minute_line_style); lv_style_set_line_width(&minute_line_style, LV_STATE_DEFAULT, 5); lv_style_set_line_color(&minute_line_style, LV_STATE_DEFAULT, lv_color_hex(0xfafafa)); lv_style_set_line_rounded(&minute_line_style, LV_STATE_DEFAULT, true); lv_obj_add_style(minute_body, LV_LINE_PART_MAIN, &minute_line_style); + lv_style_init(&hour_line_style_world); + lv_style_set_line_width(&hour_line_style_world, LV_STATE_DEFAULT, 7); + lv_style_set_line_color(&hour_line_style_world, LV_STATE_DEFAULT, lv_color_hex(0x5d3636)); + lv_style_set_line_rounded(&hour_line_style_world, LV_STATE_DEFAULT, true); + lv_obj_add_style(hour_body_world, LV_LINE_PART_MAIN, &hour_line_style_world); + lv_style_init(&hour_line_style); lv_style_set_line_width(&hour_line_style, LV_STATE_DEFAULT, 7); lv_style_set_line_color(&hour_line_style, LV_STATE_DEFAULT, lv_color_hex(0xfafafa)); @@ -182,7 +201,9 @@ WatchFaceMine::~WatchFaceMine() { lv_task_del(taskRefresh); lv_style_reset(&hour_line_style); + lv_style_reset(&hour_line_style_world); lv_style_reset(&minute_line_style); + lv_style_reset(&minute_line_style_world); lv_style_reset(&second_line_style); lv_style_reset(&tick_style); @@ -215,34 +236,36 @@ lv_line_set_points(tick[i], tick_point[i], 2); } } -void WatchFaceMine::DrawOffsetFace() { +void WatchFaceMine::DrawOffsetHands(uint8_t sHour, uint8_t sMinute, uint8_t hour, uint8_t minute) { // from https://github.com/InfiniTimeOrg/InfiniTime/pull/1454 worldClockOffset.Get(); using days = std::chrono::duration<int, std::ratio<86400>>; auto worldDateTime = dateTimeController.WorldDateTime(0); auto worldDp = std::chrono::floor<days>(worldDateTime); auto worldTime = worldDateTime - worldDp; uint8_t worldHour = std::chrono::floor<std::chrono::hours>(worldTime).count(); - int8_t offset = worldHour - dateTimeController.Hours(); - uint8_t div = 1; - switch (clockType.Get()) { - case Controllers::Settings::ClockType::H24: - div = 24; - break; - case Controllers::Settings::ClockType::H12: - div = 12; - break; - }; - for (int i = 0; i < div; ++i) { - if (offset != 0) { - auto angle = ((i-offset) * 30) / (div / 12); - tick_world_point[i][0] = CoordinateRelocate(68, angle); - tick_world_point[i][1] = CoordinateRelocate(70, angle); + + auto worldHp = std::chrono::floor<std::chrono::hours>(worldTime); + worldTime = worldTime - worldHp; + uint8_t worldMinute = std::chrono::floor<std::chrono::minutes>(worldTime).count(); + + if (sMinute != minute) { + auto const angle = worldMinute * 6; + minute_point_world[0] = CoordinateRelocate(0, angle); + minute_point_world[1] = CoordinateRelocate(MinuteLength, angle); + + lv_line_set_points(minute_body_world, minute_point_world, 2); + } + + if (sHour != hour || sMinute != minute) { + auto angle = (worldHour * 30 + worldMinute / 2); + if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) { + angle /= 2; } - else { - tick_world_point[i][0] = {.x = 0, .y = 0}; - tick_world_point[i][1] = {.x = 0, .y = 0}; - } - lv_line_set_points(tick_world[i], tick_world_point[i], 2); + + hour_point_world[0] = CoordinateRelocate(0, angle); + hour_point_world[1] = CoordinateRelocate(HourLength, angle); + + lv_line_set_points(hour_body_world, hour_point_world, 2); } } @@ -258,8 +281,8 @@ DrawFace(); } worldClockOffset = dateTimeController.worldOffset(0); - if (dateTimeController.isWorldTimeEnabled(0) && (worldClockOffset.IsUpdated() || clockTypeUpdated || sHour != hour)) { - DrawOffsetFace(); + if (dateTimeController.isWorldTimeEnabled(0) && (worldClockOffset.IsUpdated() || clockTypeUpdated || sHour != hour || sMinute != minute)) { + DrawOffsetHands(sHour, sMinute, hour, minute); } if (sSecond != second) { @@ -295,6 +318,37 @@ lv_line_set_points(hour_body, hour_point, 2); } } +void WatchFaceMine::DrawWeather() { // from https://github.com/InfiniTimeOrg/InfiniTime/pull/1856 + if (weatherService.GetCurrentTemperature()->timestamp != 0 && weatherService.GetCurrentClouds()->timestamp != 0 && + weatherService.GetCurrentPrecipitation()->timestamp != 0) { + nowTemp = (weatherService.GetCurrentTemperature()->temperature / 100); + clouds = (weatherService.GetCurrentClouds()->amount); + precip = (weatherService.GetCurrentPrecipitation()->amount); + if (nowTemp.IsUpdated()) { + std::string hawaii = decimalToDozenal(1.8 * nowTemp.Get() - 36); + lv_label_set_text_fmt(temperature, "%s", hawaii.c_str()); + if ((clouds <= 30) && (precip == 0)) { + lv_label_set_text(weatherIcon, Symbols::sun); + } else if ((clouds >= 70) && (clouds <= 90) && (precip == 1)) { + lv_label_set_text(weatherIcon, Symbols::cloudSunRain); + } else if ((clouds > 90) && (precip == 0)) { + lv_label_set_text(weatherIcon, Symbols::cloud); + } else if ((clouds > 70) && (precip >= 2)) { + lv_label_set_text(weatherIcon, Symbols::cloudShowersHeavy); + } else { + lv_label_set_text(weatherIcon, Symbols::cloudSun); + }; + lv_obj_realign(temperature); + lv_obj_realign(weatherIcon); + } + } else { + lv_label_set_text_static(temperature, ""); + lv_label_set_text(weatherIcon, ""); + lv_obj_realign(temperature); + lv_obj_realign(weatherIcon); + } +} + void WatchFaceMine::SetBatteryIcon() { auto batteryPercent = batteryPercentRemaining.Get(); batteryIcon.SetBatteryPercentage(batteryPercent); @@ -371,6 +425,8 @@ } else { lv_obj_add_style(steps_body_trace, LV_LINE_PART_MAIN, &steps_line_style_trace); } } + + // DrawWeather(); } std::string WatchFaceMine::gregorianToFixed(uint8_t day, Pinetime::Controllers::DateTime::Months month, uint16_t year) { @@ -445,3 +501,32 @@ sprintf(buf, "%s\n%s%c %d%d", weekdays[ordinal%7], moons1[moon], moons2[moon], week, sun); return std::string(buf); } + +std::string WatchFaceMine::decimalToDozenal(int16_t decimal) { + std::string result = ""; + if (decimal < 0) { + result = "-"; + decimal = -decimal; + } + uint16_t p12, rem; + while (true) { + p12 = decimal / 12; + rem = decimal % 12; + char ch; + if (rem == 11) { + ch = 'E'; + } else if (rem == 10) { + ch = 'X'; + } else { + ch = '0' + rem; + } + result += ch; + + if (p12 == 0){ + break; + } + } + + return result; +} + diff --git a/src/displayapp/screens/WatchFaceMine.h b/src/displayapp/screens/WatchFaceMine.h index c885297200c25a3fe8694431b871b1ea4d46df9c..986e930b41d66e7c93753ea541e124c761f49c30 100644 --- a/src/displayapp/screens/WatchFaceMine.h +++ b/src/displayapp/screens/WatchFaceMine.h @@ -8,6 +8,7 @@ #include "components/datetime/DateTimeController.h" #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" +#include "components/ble/weather/WeatherService.h" #include "displayapp/screens/BatteryIcon.h" #include "utility/DirtyValue.h" @@ -29,7 +30,8 @@ const Controllers::Battery& batteryController, const Controllers::Ble& bleController, Controllers::NotificationManager& notificationManager, Controllers::Settings& settingsController, - Controllers::MotionController& motionController); + Controllers::MotionController& motionController, + Controllers::WeatherService& weather); ~WatchFaceMine() override; @@ -58,15 +60,16 @@ lv_obj_t* tick[24]; lv_point_t tick_point[24][2]; - lv_obj_t* tick_world[24]; - lv_point_t tick_world_point[24][2]; - lv_obj_t* hour_body; + lv_obj_t* hour_body_world; lv_obj_t* minute_body; + lv_obj_t* minute_body_world; lv_obj_t* second_body; lv_point_t hour_point[2]; + lv_point_t hour_point_world[2]; lv_point_t minute_point[2]; + lv_point_t minute_point_world[2]; lv_point_t second_point[2]; lv_style_t tick_style; @@ -74,7 +77,9 @@ lv_style_t tick_style_zero; lv_style_t tick_style_six; lv_style_t hour_line_style; + lv_style_t hour_line_style_world; lv_style_t minute_line_style; + lv_style_t minute_line_style_world; lv_style_t second_line_style; lv_obj_t* label_date_greg; @@ -82,6 +87,12 @@ lv_obj_t* label_date_world; lv_obj_t* plugIcon; lv_obj_t* notificationIcon; lv_obj_t* bluetoothIcon; + lv_obj_t* weatherIcon; + lv_obj_t* temperature; + + Utility::DirtyValue<int16_t> nowTemp {}; + int16_t clouds = 0; + int16_t precip = 0; lv_obj_t* steps_body; lv_obj_t* steps_body_trace; @@ -99,15 +110,18 @@ const Controllers::Ble& bleController; Controllers::NotificationManager& notificationManager; Controllers::Settings& settingsController; Controllers::MotionController& motionController; + Controllers::WeatherService& weatherService; void DrawFace(); - void DrawOffsetFace(); + void DrawOffsetHands(uint8_t, uint8_t, uint8_t, uint8_t); void UpdateClock(); void SetBatteryIcon(); + void DrawWeather(); std::string gregorianToFixed(uint8_t, Pinetime::Controllers::DateTime::Months, uint16_t); bool isLeapYear(uint16_t); uint16_t gregorianToOrdinal(uint8_t, Pinetime::Controllers::DateTime::Months, bool); std::string ordinalToFixed(uint16_t, bool); + std::string decimalToDozenal(int16_t); lv_task_t* taskRefresh; };