diff --git a/include/SunPosition.h b/include/SunPosition.h index c268813c9..6d0be2d83 100644 --- a/include/SunPosition.h +++ b/include/SunPosition.h @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #pragma once +#include #include #define SUNPOS_UPDATE_INTERVAL 60000l @@ -15,9 +16,12 @@ class SunPositionClass { bool isSunsetAvailable(); bool sunsetTime(struct tm* info); bool sunriseTime(struct tm* info); + void setDoRecalc(bool doRecalc); private: void updateSunData(); + bool checkRecalcDayChanged(); + bool getDoRecalc(); SunSet _sun; bool _isDayPeriod = true; @@ -25,8 +29,10 @@ class SunPositionClass { uint32_t _sunriseMinutes = 0; uint32_t _sunsetMinutes = 0; - uint32_t _lastUpdate = 0; bool _isValidInfo = false; + bool _doRecalc = true; + std::mutex _recalcLock; + uint32_t _lastSunPositionCalculatedYMD = 0; }; -extern SunPositionClass SunPosition; \ No newline at end of file +extern SunPositionClass SunPosition; diff --git a/src/SunPosition.cpp b/src/SunPosition.cpp index a32920ec1..a23bca24e 100644 --- a/src/SunPosition.cpp +++ b/src/SunPosition.cpp @@ -19,9 +19,8 @@ void SunPositionClass::init() void SunPositionClass::loop() { - if (millis() - _lastUpdate > SUNPOS_UPDATE_INTERVAL) { + if (getDoRecalc() || checkRecalcDayChanged()) { updateSunData(); - _lastUpdate = millis(); } } @@ -35,14 +34,50 @@ bool SunPositionClass::isSunsetAvailable() return _isSunsetAvailable; } -void SunPositionClass::updateSunData() +void SunPositionClass::setDoRecalc(bool doRecalc) { - CONFIG_T const& config = Configuration.get(); - int offset = Utils::getTimezoneOffset() / 3600; - _sun.setPosition(config.Ntp_Latitude, config.Ntp_Longitude, offset); + std::lock_guard lock(_recalcLock); + _doRecalc = doRecalc; +} + +bool SunPositionClass::getDoRecalc() +{ + std::lock_guard lock(_recalcLock); + return _doRecalc; +} + +bool SunPositionClass::checkRecalcDayChanged() +{ + time_t now; + struct tm timeinfo; + + time(&now); + localtime_r(&now, &timeinfo); // don't use getLocalTime() as there could be a delay of 10ms + + uint32_t ymd; + ymd = (timeinfo.tm_year << 9) | + (timeinfo.tm_mon << 5) | + timeinfo.tm_mday; + if (_lastSunPositionCalculatedYMD != ymd) { + return true; + } + return false; +} + + +void SunPositionClass::updateSunData() +{ struct tm timeinfo; - if (!getLocalTime(&timeinfo, 5)) { + bool gotLocalTime; + + gotLocalTime = getLocalTime(&timeinfo, 5); + _lastSunPositionCalculatedYMD = (timeinfo.tm_year << 9) | + (timeinfo.tm_mon << 5) | + timeinfo.tm_mday; + setDoRecalc(false); + + if (!gotLocalTime) { _isDayPeriod = true; _sunriseMinutes = 0; _sunsetMinutes = 0; @@ -50,6 +85,10 @@ void SunPositionClass::updateSunData() return; } + CONFIG_T const& config = Configuration.get(); + int offset = Utils::getTimezoneOffset() / 3600; + + _sun.setPosition(config.Ntp_Latitude, config.Ntp_Longitude, offset); _sun.setCurrentDate(1900 + timeinfo.tm_year, timeinfo.tm_mon + 1, timeinfo.tm_mday); double sunset_type; @@ -125,4 +164,4 @@ bool SunPositionClass::sunriseTime(struct tm* info) localtime_r(&midnight, info); return _isValidInfo; -} \ No newline at end of file +} diff --git a/src/WebApi_ntp.cpp b/src/WebApi_ntp.cpp index 52c665e2c..c0cfaa441 100644 --- a/src/WebApi_ntp.cpp +++ b/src/WebApi_ntp.cpp @@ -190,6 +190,8 @@ void WebApiNtpClass::onNtpAdminPost(AsyncWebServerRequest* request) NtpSettings.setServer(); NtpSettings.setTimezone(); + + SunPosition.setDoRecalc(true); } void WebApiNtpClass::onNtpTimeGet(AsyncWebServerRequest* request) @@ -350,4 +352,4 @@ void WebApiNtpClass::onNtpTimePost(AsyncWebServerRequest* request) response->setLength(); request->send(response); -} \ No newline at end of file +}