From 943dfc2dbf070523bda3257e39feac68dbd0447b Mon Sep 17 00:00:00 2001 From: Stefan Oberhumer Date: Fri, 6 Oct 2023 10:20:36 +0200 Subject: [PATCH 1/2] Compute sunrise and sunset only if necessary. Sunrise and -set must recomputed if one of the following conditions is met: * The date changed (based on the selected timezone) * Location (Lat/Lon) changed * Sunset type changed So instead of calculating that every minute just do it on update via web interface or date change. If a new config is uploaded, the DTU gets restarted. There is no need to initiate a recalculation in this case. --- include/SunPosition.h | 10 ++++++-- src/SunPosition.cpp | 55 ++++++++++++++++++++++++++++++++++++------- src/WebApi_ntp.cpp | 4 +++- 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/include/SunPosition.h b/include/SunPosition.h index c268813c..6d0be2d8 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 @@ public: 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 @@ private: 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 a32920ec..a23bca24 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::setDoRecalc(bool doRecalc) +{ + 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() { - CONFIG_T const& config = Configuration.get(); - int offset = Utils::getTimezoneOffset() / 3600; - _sun.setPosition(config.Ntp_Latitude, config.Ntp_Longitude, offset); - 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 52c665e2..c0cfaa44 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 +} From 7f99095fcaebcc31e815f6bb4078ff74eb39bf62 Mon Sep 17 00:00:00 2001 From: Stefan Oberhumer Date: Fri, 6 Oct 2023 11:13:09 +0200 Subject: [PATCH 2/2] Remove SUNPOS_UPDATE_INTERVAL define and introduce INVERTER_UPDATE_SETTINGS_INTERVAL. --- include/InverterSettings.h | 4 +++- include/SunPosition.h | 2 -- src/InverterSettings.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/InverterSettings.h b/include/InverterSettings.h index 188025b1..6375dfcf 100644 --- a/include/InverterSettings.h +++ b/include/InverterSettings.h @@ -3,6 +3,8 @@ #include +#define INVERTER_UPDATE_SETTINGS_INTERVAL 60000l + class InverterSettingsClass { public: void init(); @@ -12,4 +14,4 @@ private: uint32_t _lastUpdate = 0; }; -extern InverterSettingsClass InverterSettings; \ No newline at end of file +extern InverterSettingsClass InverterSettings; diff --git a/include/SunPosition.h b/include/SunPosition.h index 6d0be2d8..05e3b396 100644 --- a/include/SunPosition.h +++ b/include/SunPosition.h @@ -4,8 +4,6 @@ #include #include -#define SUNPOS_UPDATE_INTERVAL 60000l - class SunPositionClass { public: SunPositionClass(); diff --git a/src/InverterSettings.cpp b/src/InverterSettings.cpp index 690f0aca..c5050bff 100644 --- a/src/InverterSettings.cpp +++ b/src/InverterSettings.cpp @@ -90,7 +90,7 @@ void InverterSettingsClass::init() void InverterSettingsClass::loop() { - if (millis() - _lastUpdate > SUNPOS_UPDATE_INTERVAL) { + if (millis() - _lastUpdate > INVERTER_UPDATE_SETTINGS_INTERVAL) { const CONFIG_T& config = Configuration.get(); for (uint8_t i = 0; i < INV_MAX_COUNT; i++) { @@ -109,4 +109,4 @@ void InverterSettingsClass::loop() } Hoymiles.loop(); -} \ No newline at end of file +}