InfiniTime.git

commit 94f41258d52102dc4863d964d43794b34f26cf41

Author: kieranc <kieranc@gmail.com>

PineTimeStyle weather display (#1459)

Weather display for PineTimeStyle

Documentation : https://wiki.pine64.org/wiki/PineTimeStyle and https://wiki.pine64.org/wiki/Infinitime-Weather

 src/components/settings/Settings.h | 14 +
 src/displayapp/DisplayApp.cpp | 7 
 src/displayapp/fonts/CMakeLists.txt | 2 
 src/displayapp/fonts/fonts.json | 12 +
 src/displayapp/screens/Clock.cpp | 5 
 src/displayapp/screens/Clock.h | 3 
 src/displayapp/screens/Symbols.h | 9 +
 src/displayapp/screens/WatchFacePineTimeStyle.cpp | 150 +++++++++++++---
 src/displayapp/screens/WatchFacePineTimeStyle.h | 14 +
 src/libs/lv_conf.h | 1 


diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h
index 0a55c08ad41261a24a02e682ff40dc302957aa52..efa44fdee46e33315d590cfcf6813d75e2c4ea99 100644
--- a/src/components/settings/Settings.h
+++ b/src/components/settings/Settings.h
@@ -39,12 +39,14 @@         Orange,
         Pink
       };
       enum class PTSGaugeStyle : uint8_t { Full, Half, Numeric };
+      enum class PTSWeather : uint8_t { On, Off };
 
       struct PineTimeStyle {
         Colors ColorTime = Colors::Teal;
         Colors ColorBar = Colors::Teal;
         Colors ColorBG = Colors::Black;
         PTSGaugeStyle gaugeStyle = PTSGaugeStyle::Full;
+        PTSWeather weatherEnable = PTSWeather::Off;
       };
 
       struct WatchFaceInfineat {
@@ -144,6 +146,16 @@       };
 
       PTSGaugeStyle GetPTSGaugeStyle() const {
         return settings.PTS.gaugeStyle;
+      };
+
+      void SetPTSWeather(PTSWeather weatherEnable) {
+        if (weatherEnable != settings.PTS.weatherEnable)
+          settingsChanged = true;
+        settings.PTS.weatherEnable = weatherEnable;
+      };
+
+      PTSWeather GetPTSWeather() const {
+        return settings.PTS.weatherEnable;
       };
 
       void SetAppMenu(uint8_t menu) {
@@ -267,7 +279,7 @@
     private:
       Pinetime::Controllers::FS& fs;
 
-      static constexpr uint32_t settingsVersion = 0x0004;
+      static constexpr uint32_t settingsVersion = 0x0005;
 
       struct SettingsData {
         uint32_t version = settingsVersion;




diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp
index fe2ee21375678fa9a76670635265b09b0d1bcb1b..a930fe961cd2492039b52c33094cee2de09bcbe8 100644
--- a/src/displayapp/DisplayApp.cpp
+++ b/src/displayapp/DisplayApp.cpp
@@ -29,6 +29,7 @@ #include "displayapp/screens/BatteryInfo.h"
 #include "displayapp/screens/Steps.h"
 #include "displayapp/screens/PassKey.h"
 #include "displayapp/screens/Error.h"
+#include "displayapp/screens/Weather.h"
 
 #include "drivers/Cst816s.h"
 #include "drivers/St7789.h"
@@ -417,6 +418,7 @@                                                        notificationManager,
                                                        settingsController,
                                                        heartRateController,
                                                        motionController,
+                                                       systemTask->nimble().weather(),
                                                        filesystem);
       break;
 
@@ -538,6 +540,11 @@       break;
     case Apps::Metronome:
       currentScreen = std::make_unique<Screens::Metronome>(motorController, *systemTask);
       break;
+    /* Weather debug app
+    case Apps::Weather:
+      currentScreen = std::make_unique<Screens::Weather>(this, systemTask->nimble().weather());
+      break;
+    */
     case Apps::Steps:
       currentScreen = std::make_unique<Screens::Steps>(motionController, settingsController);
       break;




diff --git a/src/displayapp/fonts/CMakeLists.txt b/src/displayapp/fonts/CMakeLists.txt
index 84830cc0a99be13456b39fa6bc0abe7fcdb1ca77..5a32151ec4a86ec1956e1a1ae8464eaefa2d7e72 100644
--- a/src/displayapp/fonts/CMakeLists.txt
+++ b/src/displayapp/fonts/CMakeLists.txt
@@ -1,6 +1,6 @@
 set(FONTS jetbrains_mono_42 jetbrains_mono_76 jetbrains_mono_bold_20
    jetbrains_mono_extrabold_compressed lv_font_navi_80 lv_font_sys_48
-   open_sans_light)
+   open_sans_light fontawesome_weathericons)
 find_program(LV_FONT_CONV "lv_font_conv" NO_CACHE REQUIRED
    HINTS "${CMAKE_SOURCE_DIR}/node_modules/.bin")
 message(STATUS "Using ${LV_FONT_CONV} to generate font files")




diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json
index 914ba163140ec66af328731013a7f987182824cc..e65f6dd44ae9ed8bd50639eaa36c03686f22dce2 100644
--- a/src/displayapp/fonts/fonts.json
+++ b/src/displayapp/fonts/fonts.json
@@ -3,7 +3,7 @@    "jetbrains_mono_bold_20": {
       "sources": [
          {
             "file": "JetBrainsMono-Bold.ttf",
-            "range": "0x20-0x7e, 0x410-0x44f"
+            "range": "0x20-0x7e, 0x410-0x44f, 0xB0"
          },
          {
             "file": "FontAwesome5-Solid+Brands+Regular.woff",
@@ -74,5 +74,15 @@       ],
       "bpp": 2,
       "size": 80,
       "compress": true
+   },
+   "fontawesome_weathericons": {
+      "sources": [
+         {
+            "file": "FontAwesome5-Solid+Brands+Regular.woff",
+            "range": "0xf185, 0xf6c4, 0xf743, 0xf740, 0xf75f, 0xf0c2, 0xf05e"
+         }
+      ],
+      "bpp": 1,
+      "size": 25
    }
 }




diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp
index ce70f23f9ae05d07d476936edf921d8f6801bcac..4219b090db3b9b0c8d78a44aa967a7d8a7f1e0db 100644
--- a/src/displayapp/screens/Clock.cpp
+++ b/src/displayapp/screens/Clock.cpp
@@ -24,6 +24,7 @@              Controllers::NotificationManager& notificationManager,
              Controllers::Settings& settingsController,
              Controllers::HeartRateController& heartRateController,
              Controllers::MotionController& motionController,
+             Controllers::WeatherService& weatherService,
              Controllers::FS& filesystem)
   : dateTimeController {dateTimeController},
     batteryController {batteryController},
@@ -32,6 +33,7 @@     notificationManager {notificationManager},
     settingsController {settingsController},
     heartRateController {heartRateController},
     motionController {motionController},
+    weatherService {weatherService},
     filesystem {filesystem},
     screen {[this, &settingsController]() {
       switch (settingsController.GetWatchFace()) {
@@ -95,7 +97,8 @@                                                            batteryController,
                                                            bleController,
                                                            notificationManager,
                                                            settingsController,
-                                                           motionController);
+                                                           motionController,
+                                                           weatherService);
 }
 
 std::unique_ptr<Screen> Clock::WatchFaceTerminalScreen() {




diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h
index 8c987fbbd31854789c4ead4e6a807eb1df6efca0..f3591f43c6e9437221d0088a5dadb665294d459f 100644
--- a/src/displayapp/screens/Clock.h
+++ b/src/displayapp/screens/Clock.h
@@ -7,6 +7,7 @@ #include 
 #include <components/heartrate/HeartRateController.h>
 #include "displayapp/screens/Screen.h"
 #include "components/datetime/DateTimeController.h"
+#include "components/ble/weather/WeatherService.h"
 
 namespace Pinetime {
   namespace Controllers {
@@ -28,6 +29,7 @@               Controllers::NotificationManager& notificationManager,
               Controllers::Settings& settingsController,
               Controllers::HeartRateController& heartRateController,
               Controllers::MotionController& motionController,
+              Controllers::WeatherService& weatherService,
               Controllers::FS& filesystem);
         ~Clock() override;
 
@@ -42,6 +44,7 @@         Controllers::NotificationManager& notificationManager;
         Controllers::Settings& settingsController;
         Controllers::HeartRateController& heartRateController;
         Controllers::MotionController& motionController;
+        Controllers::WeatherService& weatherService;
         Controllers::FS& filesystem;
 
         std::unique_ptr<Screen> screen;




diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h
index 934cdc3f65e2aa23393a0f97f654492815486cd4..7154ff44c1c86ab06e905e85b1c1bd866b866b60 100644
--- a/src/displayapp/screens/Symbols.h
+++ b/src/displayapp/screens/Symbols.h
@@ -38,6 +38,15 @@         static constexpr const char* eye = "\xEF\x81\xAE";
         static constexpr const char* home = "\xEF\x80\x95";
         static constexpr const char* sleep = "\xEE\xBD\x84";
 
+        // fontawesome_weathericons.c
+        // static constexpr const char* sun = "\xEF\x86\x85";
+        static constexpr const char* cloudSun = "\xEF\x9B\x84";
+        static constexpr const char* cloudSunRain = "\xEF\x9D\x83";
+        static constexpr const char* cloudShowersHeavy = "\xEF\x9D\x80";
+        static constexpr const char* smog = "\xEF\x9D\x9F";
+        static constexpr const char* cloud = "\xEF\x83\x82";
+        static constexpr const char* ban = "\xEF\x81\x9E";
+
         // lv_font_sys_48.c
         static constexpr const char* settings = "\xEE\xA2\xB8";
 




diff --git a/src/displayapp/screens/WatchFacePineTimeStyle.cpp b/src/displayapp/screens/WatchFacePineTimeStyle.cpp
index fbdabc9ecbef1001b164b8d2fc50ca5fed0999c2..250a745c1551f4cb64dbb47dd595ebf95ff919c8 100644
--- a/src/displayapp/screens/WatchFacePineTimeStyle.cpp
+++ b/src/displayapp/screens/WatchFacePineTimeStyle.cpp
@@ -33,6 +33,7 @@ #include "components/ble/NotificationManager.h"
 #include "components/motion/MotionController.h"
 #include "components/settings/Settings.h"
 #include "displayapp/DisplayApp.h"
+#include "components/ble/weather/WeatherService.h"
 
 using namespace Pinetime::Applications::Screens;
 
@@ -48,7 +49,8 @@                                                const Controllers::Battery& batteryController,
                                                const Controllers::Ble& bleController,
                                                Controllers::NotificationManager& notificationManager,
                                                Controllers::Settings& settingsController,
-                                               Controllers::MotionController& motionController)
+                                               Controllers::MotionController& motionController,
+                                               Controllers::WeatherService& weatherService)
   : currentDateTime {{}},
     batteryIcon(false),
     dateTimeController {dateTimeController},
@@ -56,7 +58,8 @@     batteryController {batteryController},
     bleController {bleController},
     notificationManager {notificationManager},
     settingsController {settingsController},
-    motionController {motionController} {
+    motionController {motionController},
+    weatherService {weatherService} {
 
   // Create a 200px wide background rectangle
   timebar = lv_obj_create(lv_scr_act(), nullptr);
@@ -94,27 +97,52 @@
   // Display icons
   batteryIcon.Create(sidebar);
   batteryIcon.SetColor(LV_COLOR_BLACK);
-  lv_obj_align(batteryIcon.GetObject(), nullptr, LV_ALIGN_IN_TOP_MID, 0, 2);
+  lv_obj_align(batteryIcon.GetObject(), nullptr, LV_ALIGN_IN_TOP_MID, 10, 2);
 
   plugIcon = lv_label_create(lv_scr_act(), nullptr);
   lv_label_set_text_static(plugIcon, Symbols::plug);
   lv_obj_set_style_local_text_color(plugIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
-  lv_obj_align(plugIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 2);
+  lv_obj_align(plugIcon, sidebar, LV_ALIGN_IN_TOP_MID, 10, 2);
 
   bleIcon = lv_label_create(lv_scr_act(), nullptr);
   lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
-  lv_label_set_text_static(bleIcon, "");
+  lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, -10, 2);
 
   notificationIcon = lv_label_create(lv_scr_act(), nullptr);
-  lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
-  lv_label_set_text_static(notificationIcon, "");
+  lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(settingsController.GetPTSColorTime()));
+  lv_obj_align(notificationIcon, timebar, LV_ALIGN_IN_TOP_LEFT, 5, 5);
+
+  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_BLACK);
+  lv_obj_set_style_local_text_font(weatherIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &fontawesome_weathericons);
+  lv_label_set_text(weatherIcon, Symbols::cloudSunRain);
+  lv_obj_align(weatherIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 35);
+  lv_obj_set_auto_realign(weatherIcon, true);
+  if (settingsController.GetPTSWeather() == Pinetime::Controllers::Settings::PTSWeather::On) {
+    lv_obj_set_hidden(weatherIcon, false);
+  } else {
+    lv_obj_set_hidden(weatherIcon, true);
+  }
+
+  temperature = lv_label_create(lv_scr_act(), nullptr);
+  lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
+  lv_obj_align(temperature, sidebar, LV_ALIGN_IN_TOP_MID, 0, 65);
+  if (settingsController.GetPTSWeather() == Pinetime::Controllers::Settings::PTSWeather::On) {
+    lv_obj_set_hidden(temperature, false);
+  } else {
+    lv_obj_set_hidden(temperature, true);
+  }
 
   // Calendar icon
   calendarOuter = lv_obj_create(lv_scr_act(), nullptr);
   lv_obj_set_style_local_bg_color(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
   lv_obj_set_style_local_radius(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
   lv_obj_set_size(calendarOuter, 34, 34);
-  lv_obj_align(calendarOuter, sidebar, LV_ALIGN_CENTER, 0, 0);
+  if (settingsController.GetPTSWeather() == Pinetime::Controllers::Settings::PTSWeather::On) {
+    lv_obj_align(calendarOuter, sidebar, LV_ALIGN_CENTER, 0, 20);
+  } else {
+    lv_obj_align(calendarOuter, sidebar, LV_ALIGN_CENTER, 0, 0);
+  }
 
   calendarInner = lv_obj_create(lv_scr_act(), nullptr);
   lv_obj_set_style_local_bg_color(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
@@ -150,17 +178,17 @@   // Display date
   dateDayOfWeek = lv_label_create(lv_scr_act(), nullptr);
   lv_obj_set_style_local_text_color(dateDayOfWeek, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
   lv_label_set_text_static(dateDayOfWeek, "THU");
-  lv_obj_align(dateDayOfWeek, sidebar, LV_ALIGN_CENTER, 0, -34);
+  lv_obj_align(dateDayOfWeek, calendarOuter, LV_ALIGN_CENTER, 0, -32);
 
   dateDay = lv_label_create(lv_scr_act(), nullptr);
   lv_obj_set_style_local_text_color(dateDay, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
   lv_label_set_text_static(dateDay, "25");
-  lv_obj_align(dateDay, sidebar, LV_ALIGN_CENTER, 0, 3);
+  lv_obj_align(dateDay, calendarOuter, LV_ALIGN_CENTER, 0, 3);
 
   dateMonth = lv_label_create(lv_scr_act(), nullptr);
   lv_obj_set_style_local_text_color(dateMonth, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
   lv_label_set_text_static(dateMonth, "MAR");
-  lv_obj_align(dateMonth, sidebar, LV_ALIGN_CENTER, 0, 32);
+  lv_obj_align(dateMonth, calendarOuter, LV_ALIGN_CENTER, 0, 32);
 
   // Step count gauge
   if (settingsController.GetPTSColorBar() == Pinetime::Controllers::Settings::Colors::White) {
@@ -323,13 +351,23 @@
   btnSteps = lv_btn_create(lv_scr_act(), nullptr);
   btnSteps->user_data = this;
   lv_obj_set_size(btnSteps, 160, 60);
-  lv_obj_align(btnSteps, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
+  lv_obj_align(btnSteps, lv_scr_act(), LV_ALIGN_CENTER, 0, -10);
   lv_obj_set_style_local_bg_opa(btnSteps, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50);
   lv_obj_t* lblSteps = lv_label_create(btnSteps, nullptr);
   lv_label_set_text_static(lblSteps, "Steps style");
   lv_obj_set_event_cb(btnSteps, event_handler);
   lv_obj_set_hidden(btnSteps, true);
 
+  btnWeather = lv_btn_create(lv_scr_act(), nullptr);
+  btnWeather->user_data = this;
+  lv_obj_set_size(btnWeather, 160, 60);
+  lv_obj_align(btnWeather, lv_scr_act(), LV_ALIGN_CENTER, 0, 60);
+  lv_obj_set_style_local_bg_opa(btnWeather, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50);
+  lv_obj_t* lblWeather = lv_label_create(btnWeather, nullptr);
+  lv_label_set_text_static(lblWeather, "Weather");
+  lv_obj_set_event_cb(btnWeather, event_handler);
+  lv_obj_set_hidden(btnWeather, true);
+
   btnSetColor = lv_btn_create(lv_scr_act(), nullptr);
   btnSetColor->user_data = this;
   lv_obj_set_size(btnSetColor, 150, 60);
@@ -337,9 +375,9 @@   lv_obj_align(btnSetColor, lv_scr_act(), LV_ALIGN_CENTER, 0, -40);
   lv_obj_set_style_local_radius(btnSetColor, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
   lv_obj_set_style_local_bg_opa(btnSetColor, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50);
   lv_obj_set_event_cb(btnSetColor, event_handler);
-  lbl_btnSetColor = lv_label_create(btnSetColor, nullptr);
-  lv_obj_set_style_local_text_font(lbl_btnSetColor, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
-  lv_label_set_text_static(lbl_btnSetColor, Symbols::paintbrushLg);
+  lv_obj_t* lblSetColor = lv_label_create(btnSetColor, nullptr);
+  lv_obj_set_style_local_text_font(lblSetColor, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
+  lv_label_set_text_static(lblSetColor, Symbols::paintbrushLg);
   lv_obj_set_hidden(btnSetColor, true);
 
   btnSetOpts = lv_btn_create(lv_scr_act(), nullptr);
@@ -349,9 +387,9 @@   lv_obj_align(btnSetOpts, lv_scr_act(), LV_ALIGN_CENTER, 0, 40);
   lv_obj_set_style_local_radius(btnSetOpts, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
   lv_obj_set_style_local_bg_opa(btnSetOpts, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50);
   lv_obj_set_event_cb(btnSetOpts, event_handler);
-  lbl_btnSetOpts = lv_label_create(btnSetOpts, nullptr);
-  lv_obj_set_style_local_text_font(lbl_btnSetOpts, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
-  lv_label_set_text_static(lbl_btnSetOpts, Symbols::settings);
+  lv_obj_t* lblSetOpts = lv_label_create(btnSetOpts, nullptr);
+  lv_obj_set_style_local_text_font(lblSetOpts, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
+  lv_label_set_text_static(lblSetOpts, Symbols::settings);
   lv_obj_set_hidden(btnSetOpts, true);
 
   taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
@@ -388,6 +426,7 @@   lv_obj_set_hidden(btnReset, true);
   lv_obj_set_hidden(btnRandom, true);
   lv_obj_set_hidden(btnClose, true);
   lv_obj_set_hidden(btnSteps, true);
+  lv_obj_set_hidden(btnWeather, true);
 }
 
 bool WatchFacePineTimeStyle::OnButtonPushed() {
@@ -403,17 +442,6 @@   auto batteryPercent = batteryPercentRemaining.Get();
   batteryIcon.SetBatteryPercentage(batteryPercent);
 }
 
-void WatchFacePineTimeStyle::AlignIcons() {
-  if (notificationState.Get() && bleState.Get()) {
-    lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 8, 25);
-    lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, -8, 25);
-  } else if (notificationState.Get() && !bleState.Get()) {
-    lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25);
-  } else {
-    lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25);
-  }
-}
-
 void WatchFacePineTimeStyle::Refresh() {
   isCharging = batteryController.IsCharging();
   if (isCharging.IsUpdated()) {
@@ -437,13 +465,12 @@   bleState = bleController.IsConnected();
   bleRadioEnabled = bleController.IsRadioEnabled();
   if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) {
     lv_label_set_text_static(bleIcon, BleIcon::GetIcon(bleState.Get()));
-    AlignIcons();
+    lv_obj_realign(bleIcon);
   }
 
   notificationState = notificationManager.AreNewNotificationsAvailable();
   if (notificationState.IsUpdated()) {
     lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(notificationState.Get()));
-    AlignIcons();
   }
 
   currentDateTime = dateTimeController.CurrentDateTime();
@@ -509,6 +536,35 @@       lv_obj_set_style_local_line_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
       lv_obj_set_style_local_scale_grad_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
     }
   }
+
+  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()) {
+      lv_label_set_text_fmt(temperature, "%d°", nowTemp.Get());
+      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, Symbols::ban);
+    lv_obj_realign(temperature);
+    lv_obj_realign(weatherIcon);
+  }
+
   if (!lv_obj_get_hidden(btnSetColor)) {
     if ((savedTick > 0) && (lv_tick_get() - savedTick > 3000)) {
       lv_obj_set_hidden(btnSetColor, true);
@@ -654,6 +710,37 @@         lv_gauge_set_critical_value(stepGauge, 100);
         settingsController.SetPTSGaugeStyle(Controllers::Settings::PTSGaugeStyle::Full);
       }
     }
+    if (object == btnWeather) {
+      if (lv_obj_get_hidden(weatherIcon)) {
+        // show weather icon and temperature
+        lv_obj_set_hidden(weatherIcon, false);
+        lv_obj_set_hidden(temperature, false);
+        lv_obj_align(calendarOuter, sidebar, LV_ALIGN_CENTER, 0, 20);
+        lv_obj_realign(calendarInner);
+        lv_obj_realign(calendarBar1);
+        lv_obj_realign(calendarBar2);
+        lv_obj_realign(calendarCrossBar1);
+        lv_obj_realign(calendarCrossBar2);
+        lv_obj_realign(dateDayOfWeek);
+        lv_obj_realign(dateDay);
+        lv_obj_realign(dateMonth);
+        settingsController.SetPTSWeather(Controllers::Settings::PTSWeather::On);
+      } else {
+        // hide weather
+        lv_obj_set_hidden(weatherIcon, true);
+        lv_obj_set_hidden(temperature, true);
+        lv_obj_align(calendarOuter, sidebar, LV_ALIGN_CENTER, 0, 0);
+        lv_obj_realign(calendarInner);
+        lv_obj_realign(calendarBar1);
+        lv_obj_realign(calendarBar2);
+        lv_obj_realign(calendarCrossBar1);
+        lv_obj_realign(calendarCrossBar2);
+        lv_obj_realign(dateDayOfWeek);
+        lv_obj_realign(dateDay);
+        lv_obj_realign(dateMonth);
+        settingsController.SetPTSWeather(Controllers::Settings::PTSWeather::Off);
+      }
+    }
     if (object == btnSetColor) {
       lv_obj_set_hidden(btnSetColor, true);
       lv_obj_set_hidden(btnSetOpts, true);
@@ -671,6 +758,7 @@     if (object == btnSetOpts) {
       lv_obj_set_hidden(btnSetColor, true);
       lv_obj_set_hidden(btnSetOpts, true);
       lv_obj_set_hidden(btnSteps, false);
+      lv_obj_set_hidden(btnWeather, false);
       lv_obj_set_hidden(btnClose, false);
     }
   }




diff --git a/src/displayapp/screens/WatchFacePineTimeStyle.h b/src/displayapp/screens/WatchFacePineTimeStyle.h
index a5c0690160931b5f6cfc2a82a85aedb610b47e25..e157bb2cd2ce682f42b45d35fa3233c41710be75 100644
--- a/src/displayapp/screens/WatchFacePineTimeStyle.h
+++ b/src/displayapp/screens/WatchFacePineTimeStyle.h
@@ -8,6 +8,7 @@ #include "displayapp/screens/Screen.h"
 #include "displayapp/screens/BatteryIcon.h"
 #include "displayapp/Colors.h"
 #include "components/datetime/DateTimeController.h"
+#include "components/ble/weather/WeatherService.h"
 #include "components/ble/BleController.h"
 #include "utility/DirtyValue.h"
 
@@ -30,7 +31,8 @@                                const Controllers::Battery& batteryController,
                                const Controllers::Ble& bleController,
                                Controllers::NotificationManager& notificationManager,
                                Controllers::Settings& settingsController,
-                               Controllers::MotionController& motionController);
+                               Controllers::MotionController& motionController,
+                               Controllers::WeatherService& weather);
         ~WatchFacePineTimeStyle() override;
 
         bool OnTouchEvent(TouchEvents event) override;
@@ -58,6 +60,9 @@         Utility::DirtyValue bleRadioEnabled {};
         Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime {};
         Utility::DirtyValue<uint32_t> stepCount {};
         Utility::DirtyValue<bool> notificationState {};
+        Utility::DirtyValue<int16_t> nowTemp {};
+        int16_t clouds = 0;
+        int16_t precip = 0;
 
         static Pinetime::Controllers::Settings::Colors GetNext(Controllers::Settings::Colors color);
         static Pinetime::Controllers::Settings::Colors GetPrevious(Controllers::Settings::Colors color);
@@ -72,6 +77,7 @@         lv_obj_t* btnReset;
         lv_obj_t* btnRandom;
         lv_obj_t* btnClose;
         lv_obj_t* btnSteps;
+        lv_obj_t* btnWeather;
         lv_obj_t* timebar;
         lv_obj_t* sidebar;
         lv_obj_t* timeDD1;
@@ -81,6 +87,8 @@         lv_obj_t* timeAMPM;
         lv_obj_t* dateDayOfWeek;
         lv_obj_t* dateDay;
         lv_obj_t* dateMonth;
+        lv_obj_t* weatherIcon;
+        lv_obj_t* temperature;
         lv_obj_t* plugIcon;
         lv_obj_t* bleIcon;
         lv_obj_t* calendarOuter;
@@ -93,8 +101,6 @@         lv_obj_t* notificationIcon;
         lv_obj_t* stepGauge;
         lv_obj_t* btnSetColor;
         lv_obj_t* btnSetOpts;
-        lv_obj_t* lbl_btnSetColor;
-        lv_obj_t* lbl_btnSetOpts;
         lv_obj_t* stepIcon;
         lv_obj_t* stepValue;
         lv_color_t needle_colors[1];
@@ -107,10 +113,10 @@         const Controllers::Ble& bleController;
         Controllers::NotificationManager& notificationManager;
         Controllers::Settings& settingsController;
         Controllers::MotionController& motionController;
+        Controllers::WeatherService& weatherService;
 
         void SetBatteryIcon();
         void CloseMenu();
-        void AlignIcons();
 
         lv_task_t* taskRefresh;
       };




diff --git a/src/libs/lv_conf.h b/src/libs/lv_conf.h
index 795760ef608860e355114428da9159a462d19974..e96778ecf823675fc6361659d78df9aef109d341 100644
--- a/src/libs/lv_conf.h
+++ b/src/libs/lv_conf.h
@@ -418,6 +418,7 @@                                LV_FONT_DECLARE(jetbrains_mono_extrabold_compressed) \
                                LV_FONT_DECLARE(jetbrains_mono_42) \
                                LV_FONT_DECLARE(jetbrains_mono_76) \
                                LV_FONT_DECLARE(open_sans_light) \
+                               LV_FONT_DECLARE(fontawesome_weathericons) \
                                LV_FONT_DECLARE(lv_font_sys_48)
 
 /* Enable it if you have fonts with a lot of characters.