diff --git a/.gitmodules b/.gitmodules index 81f93e1..5ed2bfe 100644 --- a/.gitmodules +++ b/.gitmodules @@ -61,3 +61,6 @@ [submodule "components/QRCode-esp32"] path = components/QRCode-esp32 url = ../QRCode-esp32.git +[submodule "components/sunset"] + path = components/sunset + url = ../sunset.git diff --git a/components/sunset b/components/sunset new file mode 160000 index 0000000..0520b09 --- /dev/null +++ b/components/sunset @@ -0,0 +1 @@ +Subproject commit 0520b0945c899fd2a9a4bcd13ba24d29500deb71 diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index f2e73ef..7845ddb 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -486,7 +486,7 @@ set(sources set(dependencies freertos nvs_flash esp_http_server esp_https_ota mdns app_update esp_system esp_websocket_client driver arduino-esp32 ArduinoJson esp-nimble-cpp FastLED-idf TFT_eSPI QRCode-esp32 - bobbycar-protocol cpputils cxx-ring-buffer date + bobbycar-protocol cpputils cxx-ring-buffer date sunset espasynchttpreq espasyncota espchrono espcpputils espconfiglib esp-gui-lib esphttpdutils espwifistack expected fmt ) diff --git a/main/accessors/settingsaccessors.h b/main/accessors/settingsaccessors.h index 76c4733..02bc2b8 100644 --- a/main/accessors/settingsaccessors.h +++ b/main/accessors/settingsaccessors.h @@ -194,6 +194,7 @@ struct LedstripBrightnessAccessor : public NewSettingsAccessor { Config struct LedstripEnableBlinkAnimationAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.ledstrip.enableAnimBlink; } }; struct LedstripOtaAnimationAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.ledstrip.otaMode; } }; struct LedstripEnableVisualizeBlinkAnimationAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.ledstrip.enableVisualizeBlink; } }; +struct LedstripAutomaticLightAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.ledstrip.automaticLight; } }; // Battery struct BatterySeriesCellsAccessor : public NewSettingsAccessor { ConfigWrapper &getConfig() const override { return configs.battery.cellsSeries; } }; diff --git a/main/displays/menus/ledstripmenu.cpp b/main/displays/menus/ledstripmenu.cpp index d08f7a8..c89b214 100644 --- a/main/displays/menus/ledstripmenu.cpp +++ b/main/displays/menus/ledstripmenu.cpp @@ -42,6 +42,7 @@ constexpr char TEXT_LEDSTRIP_STVO[] = "Enable StVO"; constexpr char TEXT_STVO_FRONTOFFSET[] = "StVO Front Offset"; constexpr char TEXT_STVO_FRONTLENGTH[] = "StVO Front Length"; constexpr char TEXT_STVO_ENABLEFRONTLIGHT[] = "StVO Front Enable"; +constexpr char TEXT_AUTOMATIC_LIGHTS[] = "Automatic Lights"; constexpr char TEXT_ANIMATION_MULTIPLIER[] = "Animation Multiplier"; constexpr char TEXT_LEDSTRIP_BRIGHTNESS[] = "Ledstrip Brightness"; constexpr char TEXT_LEDSTRIP_ALLCUSTOMOFF[] = "All custom off"; @@ -150,6 +151,7 @@ LedstripMenu::LedstripMenu() if (!simplified) { constructMenuItem, BobbyCheckbox, EnableLedstripStVOAccessor>>(); } constructMenuItem, BobbyCheckbox, EnableLedstripStVOFrontlight>>(); + constructMenuItem, BobbyCheckbox, LedstripAutomaticLightAccessor>>(); constructMenuItem, BobbyCheckbox, EnableLedAnimationAccessor>>(); constructMenuItem>(&configs.ledstrip.animationType); diff --git a/main/displays/menus/timesettingsmenu.cpp b/main/displays/menus/timesettingsmenu.cpp index a94a26f..507a644 100644 --- a/main/displays/menus/timesettingsmenu.cpp +++ b/main/displays/menus/timesettingsmenu.cpp @@ -13,6 +13,7 @@ #include "actions/dummyaction.h" #include "icons/back.h" #include "espstrutils.h" +#include // local includes #include "displays/bobbychangevaluedisplay.h" @@ -53,6 +54,26 @@ public: } }; +class SuntimeText : public virtual espgui::TextInterface +{ +public: + std::string text() const override + { + SunSet sunSet; + sunSet.setPosition(47.076668, 15.421371, 2); // Vienna + sunSet.setTZOffset(2); + const auto today = toDateTime(espchrono::utc_clock::now()); + sunSet.setCurrentDate(static_cast(today.date.year()), static_cast(today.date.month()), static_cast(today.date.day())); + const auto sunrise = static_cast(sunSet.calcSunrise()); + const auto sunset = static_cast(sunSet.calcSunset()); + const int sunriseHour = sunrise / 60; + const int sunriseMinute = sunrise % 60; + const int sunsetHour = sunset / 60; + const int sunsetMinute = sunset % 60; + return fmt::format("sunrise: {}:{:02d} sunset: {}:{:02d}", sunriseHour, sunriseMinute, sunsetHour, sunsetMinute); + } +}; + using TimezoneOffsetChangeDisplay = espgui::makeComponent< BobbyChangeValueDisplay, espgui::StaticText, @@ -108,6 +129,7 @@ TimeSettingsMenu::TimeSettingsMenu() using namespace espgui; constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); + constructMenuItem, DummyAction>>(); constructMenuItem, SwitchScreenAction>>(); constructMenuItem, SwitchScreenAction>>(); if (configs.feature.ntp.isEnabled.value) diff --git a/main/ledstrip.cpp b/main/ledstrip.cpp index 276932a..52a050e 100644 --- a/main/ledstrip.cpp +++ b/main/ledstrip.cpp @@ -1,15 +1,16 @@ #include "ledstrip.h" // 3rdparty lib includes +#include +#include +#include // local includes #include "globals.h" -#include "cpputils.h" -#include "espchrono.h" #include "ledstripdefines.h" -#include "utils.h" -#include "ota.h" #include "newsettings.h" +#include "ota.h" +#include "utils.h" using namespace std::chrono_literals; @@ -182,7 +183,9 @@ void updateLedStrip() } else if ((cpputils::is_in(blinkAnimation, LEDSTRIP_OVERWRITE_BLINKLEFT, LEDSTRIP_OVERWRITE_BLINKRIGHT, LEDSTRIP_OVERWRITE_BLINKBOTH)) && configs.ledstrip.enableBeepWhenBlink.value) have_disabled_beeper = false; - if (simplified || configs.ledstrip.enableStVO.value) + const auto automaticLight = activateAutomaticFrontLight(); + + if (simplified || configs.ledstrip.enableStVO.value || automaticLight) { const auto center = (std::begin(leds) + (leds.size() / 2) + configs.ledstrip.centerOffset.value); @@ -197,7 +200,7 @@ void updateLedStrip() std::fill(center + configs.ledstrip.smallOffset.value + 1U, center + configs.ledstrip.bigOffset.value + 1U, CRGB{255, 0, 0}); // Left } - if (configs.ledstrip.stvoFrontEnable.value) + if (configs.ledstrip.stvoFrontEnable.value || automaticLight) { std::fill(std::begin(leds) + configs.ledstrip.stvoFrontOffset.value, std::begin(leds) + configs.ledstrip.stvoFrontOffset.value + configs.ledstrip.stvoFrontLength.value, CRGB{255, 255, 255}); std::fill(std::end(leds) - configs.ledstrip.stvoFrontOffset.value - configs.ledstrip.stvoFrontLength.value, std::end(leds) - configs.ledstrip.stvoFrontOffset.value, CRGB{255, 255, 255}); @@ -353,3 +356,17 @@ void showCustomColor() std::fill(center - (eighth_length / 2) - eighth_length - eighth_length - eighth_length, center - (eighth_length / 2) - eighth_length - eighth_length, configs.ledstrip.custom_color[int(Bobbycar_Side::FRONT_LEFT)].value); // Front Left #endif } + +[[nodiscard]] bool activateAutomaticFrontLight() +{ + if (!configs.ledstrip.automaticLight.value) + return false; + SunSet sunSet; + sunSet.setPosition(47.076668, 15.421371, 0); // Vienna + sunSet.setTZOffset(0); + const auto today = toDateTime(espchrono::utc_clock::now()); + sunSet.setCurrentDate(static_cast(today.date.year()), static_cast(today.date.month()), static_cast(today.date.day())); + const auto sunrise = static_cast(sunSet.calcSunrise()) / 60; + const auto sunset = static_cast(sunSet.calcSunset()) / 60; + return (today.hour >= sunrise && today.hour < sunset); +} diff --git a/main/ledstrip.h b/main/ledstrip.h index 06f0037..1aa7d75 100644 --- a/main/ledstrip.h +++ b/main/ledstrip.h @@ -49,3 +49,5 @@ void showOtaAnimation(); void initLedStrip(); void updateLedStrip(); + +[[nodiscard]] bool activateAutomaticFrontLight(); diff --git a/main/newsettings.h b/main/newsettings.h index 981be8b..a4cc301 100644 --- a/main/newsettings.h +++ b/main/newsettings.h @@ -294,6 +294,7 @@ public: ConfigWrapper {0, DoReset, {}, "ledCustomCol8" }, }; ConfigWrapper leds_per_meter {144, DoReset, {}, "ledsPerMeter" }; + ConfigWrapper automaticLight {false, DoReset, {}, "nightLights" }; } ledstrip; struct { @@ -600,7 +601,8 @@ public: x(ledstrip.enableAnimBlink) \ x(ledstrip.otaMode) \ x(ledstrip.maxMilliamps) \ - x(ledstrip.enableVisualizeBlink) \ + x(ledstrip.enableVisualizeBlink)\ + x(ledstrip.automaticLight) \ \ x(ledstrip.custom_color[0]) \ x(ledstrip.custom_color[1]) \ diff --git a/main/utils.cpp b/main/utils.cpp index 4304e3e..e87c634 100644 --- a/main/utils.cpp +++ b/main/utils.cpp @@ -338,3 +338,9 @@ float float_map(float x, float in_min, float in_max, float out_min, float out_ma return (delta * dividend + (divisor / 2.f)) / divisor + out_min; } + +bool is_valid_timestamp(espchrono::utc_clock::time_point timestamp) +{ + using namespace date; + return timestamp.time_since_epoch() > sys_seconds{sys_days{1_d/January/2000}}.time_since_epoch(); +} diff --git a/main/utils.h b/main/utils.h index bb87bf7..032ea38 100644 --- a/main/utils.h +++ b/main/utils.h @@ -80,3 +80,4 @@ inline CRGB UINT32_TO_CRGB(uint32_t color) std::string get_wifi_security_string(wifi_auth_mode_t authMode); float float_map(float x, float in_min, float in_max, float out_min, float out_max); +bool is_valid_timestamp(espchrono::utc_clock::time_point timestamp);