-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: night mode — extended sleep interval during 22:00-06:00 #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feat/power-optimization
Are you sure you want to change the base?
Changes from all commits
eeb8a6f
a7d7dbf
6a4f196
0bdf956
ec569c0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,6 +67,7 @@ PoolMonitorContext::~PoolMonitorContext() { | |
| Self = nullptr; | ||
| } | ||
|
|
||
| // cppcheck-suppress unusedFunction ; called from main.cpp (cross-TU) | ||
| auto PoolMonitorContext::setup() -> void { | ||
| Serial.println(F(" ------------------------------------- ")); | ||
| Serial.println(F("| Pool Monitor |")); | ||
|
|
@@ -98,9 +99,13 @@ auto PoolMonitorContext::setup() -> void { | |
|
|
||
| // Track cumulative uptime across sleep cycles | ||
| unsigned long total_uptime = preferences_->getULong("total_uptime", 0); | ||
| total_uptime += TIME_TO_SLEEP_SECONDS; | ||
| // Use actual sleep duration from last cycle (supports night-mode 4h sleeps) | ||
| uint32_t lastSleepDuration = preferences_->getUInt("last_sleep_sec", TIME_TO_SLEEP_SECONDS); | ||
| total_uptime += lastSleepDuration; | ||
| preferences_->remove("last_sleep_sec"); | ||
| preferences_->putULong("total_uptime", total_uptime); | ||
| Serial.printf("Total uptime: %lu seconds (%.1f hours)\n", total_uptime, total_uptime / 3600.0); | ||
| Serial.printf("Total uptime: %lu seconds (%.1f hours, last sleep: %u s)\n", | ||
| total_uptime, total_uptime / 3600.0, lastSleepDuration); | ||
|
|
||
| // ── Power-save: WiFi/MQTT only every (SKIP_WIFI_WAKE_CYCLES + 1) wake-ups ── | ||
| uint32_t cyclesWithoutWiFi = preferences_->getUInt("no_wifi_count", 0); | ||
|
|
@@ -109,15 +114,23 @@ auto PoolMonitorContext::setup() -> void { | |
| bool hasConfig = (preferences_->getString("mqtt_server", "").length() > 0); | ||
| bool doNetwork = !hasConfig || (cyclesWithoutWiFi >= SKIP_WIFI_WAKE_CYCLES); | ||
|
|
||
| // Scale no_wifi_count increment by actual sleep duration so a 4-hour | ||
| // night sleep advances the counter by ~80 cycles (14400/180) instead | ||
| // of only 1, preventing network-skip on the post-night wake. | ||
| uint32_t skipIncrement = lastSleepDuration / TIME_TO_SLEEP_SECONDS; | ||
| if (skipIncrement < 1) skipIncrement = 1; | ||
|
|
||
| if (doNetwork) { | ||
| preferences_->putUInt("no_wifi_count", 0); | ||
| } else { | ||
| preferences_->putUInt("no_wifi_count", cyclesWithoutWiFi + 1); | ||
| preferences_->putUInt("no_wifi_count", cyclesWithoutWiFi + skipIncrement); | ||
| } | ||
| Serial.printf("📡\tNetwork cycle: %s (%u/%u without WiFi)\n", | ||
| Serial.printf("📡\tNetwork cycle: %s (%u/%u without WiFi, last sleep: %u s, inc: %u)\n", | ||
| doNetwork ? "YES" : "NO", | ||
| doNetwork ? 0 : cyclesWithoutWiFi + 1, | ||
| SKIP_WIFI_WAKE_CYCLES); | ||
| SKIP_WIFI_WAKE_CYCLES, | ||
| lastSleepDuration, | ||
| skipIncrement); | ||
|
|
||
| // Initialize NTP time client | ||
| PoolMonitor::beginTimeClient(); | ||
|
|
@@ -199,11 +212,56 @@ auto PoolMonitorContext::loop() -> void { | |
| } | ||
|
|
||
| auto PoolMonitorContext::prepareForSleep() -> void { | ||
| Serial.printf("😴\tGoing to sleep now for %d sec.\n", TIME_TO_SLEEP_SECONDS); | ||
| // ── Determine sleep interval ── | ||
| uint32_t sleepSeconds = TIME_TO_SLEEP_SECONDS; | ||
|
|
||
| unsigned long totalUptime = preferences_->getULong("total_uptime", 0); | ||
| unsigned long lastEpoch = preferences_->getULong("last_epoch", 0); | ||
|
|
||
| if (lastEpoch > 0) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an NTP update fails after WiFi connects, Useful? React with 👍 / 👎. |
||
| // Reconstruct current local time to check if we're in the night window | ||
| unsigned long lastNtpSync = preferences_->getULong("last_ntp_sync", 0); | ||
| unsigned long elapsed = 0; | ||
| if (totalUptime > lastNtpSync) { | ||
| elapsed = totalUptime - lastNtpSync; | ||
| } | ||
| time_t t = PoolMonitor::currentTZ.toLocal(lastEpoch + elapsed); | ||
| int currentHour = ::hour(t); | ||
| int currentMinute = ::minute(t); | ||
| int currentSecond = ::second(t); | ||
|
|
||
| if (currentHour >= static_cast<int>(NIGHT_START_HOUR) || | ||
| currentHour < static_cast<int>(NIGHT_END_HOUR)) { | ||
| sleepSeconds = NIGHT_SLEEP_INTERVAL_SECONDS; | ||
|
stritti marked this conversation as resolved.
stritti marked this conversation as resolved.
stritti marked this conversation as resolved.
|
||
|
|
||
| // Clamp night sleep so the device does not overshoot NIGHT_END_HOUR | ||
| int secondsUntilEnd; | ||
| if (currentHour >= static_cast<int>(NIGHT_START_HOUR)) { | ||
| // Night started today (22:xx-23:xx), end is tomorrow 06:xx | ||
| secondsUntilEnd = (static_cast<int>(NIGHT_END_HOUR) + 24 - currentHour) * 3600 | ||
| - currentMinute * 60 - currentSecond; | ||
| } else { | ||
| // Night continues today (00:xx-05:xx), end is today 06:xx | ||
| secondsUntilEnd = (static_cast<int>(NIGHT_END_HOUR) - currentHour) * 3600 | ||
| - currentMinute * 60 - currentSecond; | ||
| } | ||
|
|
||
| if (secondsUntilEnd > 60 && sleepSeconds > static_cast<uint32_t>(secondsUntilEnd)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When the device evaluates night mode in the last minute before Useful? React with 👍 / 👎. |
||
| sleepSeconds = secondsUntilEnd; | ||
| Serial.printf("🌙\tClamping night sleep to %d sec (wake at %02d:00)\n", | ||
| sleepSeconds, NIGHT_END_HOUR); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Serial.printf("😴\tGoing to sleep now for %d sec.\n", sleepSeconds); | ||
|
|
||
| // Save current state | ||
| saveState(); | ||
|
|
||
| // Persist actual sleep duration for correct uptime tracking next boot | ||
| preferences_->putUInt("last_sleep_sec", sleepSeconds); | ||
|
|
||
| // Disconnect MQTT | ||
| NetworkManager::disconnectMqtt(); | ||
|
|
||
|
|
@@ -214,7 +272,7 @@ auto PoolMonitorContext::prepareForSleep() -> void { | |
| preferences_->end(); | ||
|
|
||
| // Enter deep sleep | ||
| esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP_SECONDS * 1000000); | ||
| esp_sleep_enable_timer_wakeup(sleepSeconds * 1000000ULL); | ||
| pinMode(PIN_MODEM_POWER_ON, OUTPUT); | ||
| digitalWrite(PIN_MODEM_POWER_ON, LOW); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the previous sleep was a night interval and
no_wifi_countwas still below the threshold,doNetworkhas already been computed before this scaled increment is written, so that wake still skips WiFi/MQTT even though 4 hours elapsed; for example, entering night right after a network cycle makes the 02:00 wake skip the retained MQTT sample and display update. Fresh evidence in this revision is that the scaled increment is only persisted here after the network decision was made, so the intended long-sleep catch-up applies one wake too late.Useful? React with 👍 / 👎.