diff --git a/src/config.h b/src/config.h index 4fb42d3..3f99bce 100644 --- a/src/config.h +++ b/src/config.h @@ -50,6 +50,11 @@ constexpr float RANGE_STEPS_KM[] = {10.0f, 25.0f, 50.0f, 100.0f}; constexpr uint8_t RANGE_STEP_COUNT = 4; constexpr uint8_t DEFAULT_RANGE_INDEX = 1; + // Eco-Mode: reduziert die ADS-B-Abfragefrequenz auf dieses Intervall + // (statt FETCH_INTERVAL_MS), wenn der Bildschirm durch Inaktivitaets- + // Timeout abgeschaltet ist (siehe main.cpp). + constexpr uint32_t ECO_FETCH_INTERVAL_MS = 60000; + constexpr uint8_t ALT_FILTER_COUNT = 3; constexpr uint8_t DEFAULT_ALT_FILTER_INDEX = 0; diff --git a/src/i18n.h b/src/i18n.h index 860e90f..10f387c 100644 --- a/src/i18n.h +++ b/src/i18n.h @@ -354,6 +354,7 @@ enum class StringId : uint8_t { TIMEOUT_SCREEN_TITLE, TIMEOUT_SCREENSAVER_DESC, + MENU_ECO_MODE, MENU_ROUTE_FILTER, ROUTE_FILTER_PROMPT, diff --git a/src/i18n_de.h b/src/i18n_de.h index de6234f..9c851c5 100644 --- a/src/i18n_de.h +++ b/src/i18n_de.h @@ -253,8 +253,9 @@ static const char* const I18N_DE[] = { "Die neue Firmware wurde erfolgreich installiert. Bitte jetzt neu starten, um sie zu verwenden.", "Jetzt neu starten", "Das Update konnte nicht heruntergeladen oder installiert werden. Das Gerät läuft unverändert mit der bisherigen Firmware weiter. Bitte WLAN-Verbindung prüfen und es später erneut versuchen.", - "Bildschirm-Timeout", -"Nach dieser Zeit ohne Berührung schaltet sich das Display ab, um Strom zu sparen. Ist der Ruhebildschirm aktiviert, zeigt es stattdessen einen gedimmten Sternenhimmel mit Uhrzeit.", +"Bildschirm-Timeout", + "Nach dieser Zeit ohne Berührung schaltet sich das Display ab, um Strom zu sparen. Ist der Ruhebildschirm aktiviert, zeigt es stattdessen einen gedimmten Sternenhimmel mit Uhrzeit.", + "Eco Mode", "Streckenfilter", "ICAO eingeben", }; diff --git a/src/i18n_en.h b/src/i18n_en.h index 4f94de5..4d22181 100644 --- a/src/i18n_en.h +++ b/src/i18n_en.h @@ -256,6 +256,7 @@ static const char* const I18N_EN[] = { "The update could not be downloaded or installed. The device is still running the previous firmware, unchanged. Please check your WiFi connection and try again later.", "Screen Timeout", "After this time without touch, the display turns off to save power. With the screensaver on, it dims to a starfield with a clock instead.", + "Eco Mode", "Route Filter", "Enter ICAO", }; diff --git a/src/i18n_es.h b/src/i18n_es.h index 5a201e0..0554faa 100644 --- a/src/i18n_es.h +++ b/src/i18n_es.h @@ -253,8 +253,9 @@ static const char* const I18N_ES[] = { "El nuevo firmware se instaló correctamente. Reinicia ahora para empezar a usarlo.", "Reiniciar ahora", "No se pudo descargar o instalar la actualización. El dispositivo sigue funcionando sin cambios con el firmware anterior. Comprueba tu conexión WiFi e inténtalo de nuevo más tarde.", - "Tiempo de espera de pantalla", -"Tras este tiempo sin toques, la pantalla se apaga para ahorrar energía. Con el salvapantallas activado, muestra en su lugar un cielo estrellado atenuado con la hora.", +"Tiempo de espera de pantalla", + "Tras este tiempo sin toques, la pantalla se apaga para ahorrar energía. Con el salvapantallas activado, muestra en su lugar un cielo estrellado atenuado con la hora.", + "Eco Mode", "Filtro de ruta", "Ingresa OACI", }; diff --git a/src/i18n_fr.h b/src/i18n_fr.h index 83d2e02..e37646b 100644 --- a/src/i18n_fr.h +++ b/src/i18n_fr.h @@ -253,8 +253,9 @@ static const char* const I18N_FR[] = { "Le nouveau micrologiciel a été installé avec succès. Veuillez redémarrer maintenant pour l'utiliser.", "Redémarrer maintenant", "La mise à jour n'a pas pu être téléchargée ou installée. L'appareil continue de fonctionner normalement avec le micrologiciel précédent. Merci de vérifier votre connexion WiFi et de réessayer plus tard.", - "Délai d'inactivité", -"Après ce délai sans contact, l'écran s'éteint pour économiser l'énergie. Avec l'écran de veille activé, il affiche à la place un ciel étoilé tamisé avec l'heure.", +"Délai d'inactivité", + "Après ce délai sans contact, l'écran s'éteint pour économiser l'énergie. Avec l'écran de veille activé, il affiche à la place un ciel étoilé tamisé avec l'heure.", + "Eco Mode", "Filtre d'itinéraire", "Entrer code OACI", }; diff --git a/src/i18n_it.h b/src/i18n_it.h index 7f4c0b7..dc66d04 100644 --- a/src/i18n_it.h +++ b/src/i18n_it.h @@ -253,8 +253,9 @@ static const char* const I18N_IT[] = { "Il nuovo firmware è stato installato correttamente. Riavvia ora per iniziare a usarlo.", "Riavvia ora", "Non è stato possibile scaricare o installare l'aggiornamento. Il dispositivo continua a funzionare senza modifiche con il firmware precedente. Controlla la connessione WiFi e riprova più tardi.", - "Timeout schermo", -"Dopo questo tempo senza tocchi, lo schermo si spegne per risparmiare energia. Con il salvaschermo attivo, mostra invece un cielo stellato attenuato con l'orario.", +"Timeout schermo", + "Dopo questo tempo senza tocchi, lo schermo si spegne per risparmiare energia. Con il salvaschermo attivo, mostra invece un cielo stellato attenuato con l'orario.", + "Eco Mode", "Filtro rotta", "Inserisci ICAO", }; diff --git a/src/i18n_tr.h b/src/i18n_tr.h index d94dbe5..364f9b7 100644 --- a/src/i18n_tr.h +++ b/src/i18n_tr.h @@ -253,8 +253,9 @@ static const char* const I18N_TR[] = { "Yeni donanım yazılımı başarıyla yüklendi. Kullanmaya başlamak için lütfen şimdi yeniden başlatın.", "Şimdi yeniden başlat", "Güncelleme indirilemedi veya yüklenemedi. Cihaz değişmeden önceki donanım yazılımıyla çalışmaya devam ediyor. Lütfen WiFi bağlantınızı kontrol edip daha sonra tekrar deneyin.", - "Ekran Zaman Aşımı", -"Bu süre boyunca dokunulmazsa ekran güç tasarrufu için kapanır. Ekran koruyucu açıksa, bunun yerine saatli, sönük bir yıldızlı gökyüzü gösterir.", +"Ekran Zaman Aşımı", + "Bu süre boyunca dokunulmazsa ekran güç tasarrufu için kapanır. Ekran koruyucu açıksa, bunun yerine saatli, sönük bir yıldızlı gökyüzü gösterir.", + "Eco Mode", "Rota Filtresi", "ICAO Girin", }; diff --git a/src/main.cpp b/src/main.cpp index 2088a8d..ff836a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -664,23 +664,20 @@ void loop() { lastInteractionMs = millis(); if (screenDimmed) { - bool shouldNightDim = SettingsStore::nightDimmingEnabled() && isNightDimHours(); +bool shouldNightDim = SettingsStore::nightDimmingEnabled() && isNightDimHours(); ledcWrite(BACKLIGHT_PWM_CHANNEL, shouldNightDim ? nightDimBacklightPwm() : normalBacklightPwm()); nightDimActive = shouldNightDim; screenDimmed = false; tapped = false; if (screensaverShowing) { - // Der Ruhebildschirm hat den kompletten Bildschirminhalt - // ueberschrieben (Sternenhimmel + Uhrzeit) - anders als beim - // normalen Timeout (nur Backlight aus, Inhalt blieb im - // TFT-Speicher unveraendert stehen) muss hier explizit neu - // gezeichnet werden. screensaverShowing = false; drawHeader(); updateStatusLine(); forceRedraw = true; } + NetTask::setFetchInterval(Config::FETCH_INTERVAL_MS); + WiFi.setSleep(false); } } @@ -746,29 +743,19 @@ forceRedraw = false; if (!screenDimmed && timeoutMin > 0) { uint32_t timeoutMs = (uint32_t)timeoutMin * 60000UL; if (nowMs - lastInteractionMs >= timeoutMs) { - if (SettingsStore::screensaverEnabled()) { - // Ruhebildschirm statt komplett dunkel (Menue > System > - // Ruhebildschirm, AUS per Default) - gedimmter - // Sternenhimmel mit grosser Uhrzeit statt des Backlights - // ganz aus, fuer alle, die trotz Inaktivitaets-Timeout noch - // etwas auf dem Display sehen wollen. +if (SettingsStore::screensaverEnabled()) { screensaverShowing = true; ledcWrite(BACKLIGHT_PWM_CHANNEL, nightDimBacklightPwm()); tft.fillScreen(TFT_BLACK); MenuStars::reset(); - lastScreensaverClockMs = 0; // sofortiges erstes Zeichnen erzwingen + lastScreensaverClockMs = 0; } else { - // Bewusst ganz aus (0) statt nur gedimmt - fuer den - // Bildschirm-Timeout (Menue > System > Timeout). Dimmen - // uebernimmt bereits der separate Nachtmodus - // (updateNightDimming()); der Inaktivitaets-Timeout soll das - // Display wirklich abschalten, z.B. fuer Plane-Spotter, die nur - // das Flugbuch mitlaufen lassen wollen, ohne den Screen zu - // brauchen. Ein Antippen weckt ihn ueber den screenDimmed-Zweig - // oben wieder auf die eingestellte Helligkeit (bzw. Nachtmodus- - // Helligkeit, falls gerade Nachtstunden sind). ledcWrite(BACKLIGHT_PWM_CHANNEL, 0); } + if (SettingsStore::ecoModeEnabled()) { + NetTask::setFetchInterval(Config::ECO_FETCH_INTERVAL_MS); + WiFi.setSleep(true); + } screenDimmed = true; } } diff --git a/src/menu_screen.cpp b/src/menu_screen.cpp index adb649c..5355840 100644 --- a/src/menu_screen.cpp +++ b/src/menu_screen.cpp @@ -93,7 +93,7 @@ namespace { // Ruhebildschirm-Umschalter, der zwischenzeitlich hier eine eigene // Zeile hatte, ist in den neuen Bildschirm-Timeout-Screen umgezogen // (siehe timeout_screen.cpp) - Zeilenzahl bleibt dadurch bei 10. - constexpr uint8_t SYSTEM_ROW_COUNT = 10; + constexpr uint8_t SYSTEM_ROW_COUNT = 11; // +1 fuer Eco-Mode constexpr int16_t SYSTEM_ROW_GAP = 4; constexpr int16_t SYSTEM_START_Y = 18; constexpr int16_t SYSTEM_END_Y = Config::SCREEN_HEIGHT - 10; @@ -672,17 +672,18 @@ void run(TFT_eSPI& tft) { Rect brightnessBtn = systemRowRect(2); Rect timeoutBtn = systemRowRect(3); Rect nightDimBtn = systemRowRect(4); - Rect webuiBtn = systemRowRect(5); + Rect webuiBtn = systemRowRect(6); // "Sicherung & Reset" (Backup/Restore/Werksreset, siehe // Page::BackupReset unten) und "Nach Update suchen" stehen // bewusst direkt ueber "Info", das seinerseits als letzter // Punkt direkt ueber dem Zurueck-Button steht - so bleiben // beide Positionen stabil, egal wie viele weitere Punkte davor // noch dazukommen. - Rect backupResetBtn = systemRowRect(6); - Rect checkUpdateBtn = systemRowRect(7); - Rect aboutBtn = systemRowRect(8); - Rect backBtn = systemRowRect(9); + Rect ecoModeBtn = systemRowRect(5); + Rect backupResetBtn = systemRowRect(7); + Rect checkUpdateBtn = systemRowRect(8); + Rect aboutBtn = systemRowRect(9); + Rect backBtn = systemRowRect(10); drawButton(tft, calibBtn, I18n::t(StringId::MENU_CALIBRATE)); @@ -725,14 +726,16 @@ void run(TFT_eSPI& tft) { TimeoutScreen::run(tft); } else if (nightDimBtn.contains(tap.x, tap.y)) { SettingsStore::setNightDimmingEnabled(!SettingsStore::nightDimmingEnabled()); + } else if (ecoModeBtn.contains(tap.x, tap.y)) { + SettingsStore::setEcoModeEnabled(!SettingsStore::ecoModeEnabled()); + } else if (webuiBtn.contains(tap.x, tap.y)) { + WebUiScreen::run(tft); } else if (backupResetBtn.contains(tap.x, tap.y)) { page = Page::BackupReset; } else if (checkUpdateBtn.contains(tap.x, tap.y)) { runOtaUpdateScreen(tft); } else if (aboutBtn.contains(tap.x, tap.y)) { AboutScreen::run(tft); - } else if (webuiBtn.contains(tap.x, tap.y)) { - WebUiScreen::run(tft); } else if (backBtn.contains(tap.x, tap.y)) { page = Page::Main; } diff --git a/src/net_task.cpp b/src/net_task.cpp index 5245ae9..e0b8c46 100644 --- a/src/net_task.cpp +++ b/src/net_task.cpp @@ -21,6 +21,7 @@ namespace NetTask { namespace { TaskHandle_t taskHandle = nullptr; uint32_t lastFetchMs = 0; + uint32_t fetchIntervalMs = Config::FETCH_INTERVAL_MS; Aircraft tempTable[Config::MAX_TRACKED_AIRCRAFT]; @@ -42,7 +43,7 @@ namespace { AircraftDetails::update(); Weather::update(); - if (millis() - lastFetchMs >= Config::FETCH_INTERVAL_MS) { + if (millis() - lastFetchMs >= fetchIntervalMs) { lastFetchMs = millis(); if (WifiMgr::getState() == WifiMgr::State::Connected) { @@ -103,4 +104,8 @@ void resume() { if (taskHandle) vTaskResume(taskHandle); } +void setFetchInterval(uint32_t ms) { + fetchIntervalMs = ms; +} + } \ No newline at end of file diff --git a/src/net_task.h b/src/net_task.h index 640d65f..7b89fc6 100644 --- a/src/net_task.h +++ b/src/net_task.h @@ -1,19 +1,17 @@ #pragma once +#include // Hintergrund-Task fuer WLAN-Status, Standortbestimmung und ADS-B-Abfragen. // Laeuft auf Core 0, damit Core 1 (Rendering + Touch im main-Loop) nie durch // Netzwerk-Wartezeiten (WLAN, HTTPS) blockiert wird. namespace NetTask { - // Startet den Hintergrund-Task. Muss erst NACH WifiMgr::init() und - // LocationManager::init() aufgerufen werden. void begin(); - - // Haelt den Hintergrund-Task an bzw. setzt ihn fort - z.B. waehrend - // eines OTA-Updates, da der ESP32 nur eine WLAN-Funkeinheit/einen - // gemeinsamen Netzwerk-Stack fuer beide Cores hat und gleichzeitige - // Anfragen (ADS-B-Polling im Hintergrund vs. OTA-Download) sich in die - // Quere kommen koennen. Beide sicher mehrfach aufrufbar bzw. ohne - // Wirkung, falls der Task noch nicht gestartet ist. void pause(); void resume(); + + // Eco-Mode: aendert das ADS-B-Abfrage-Intervall zur Laufzeit. + // Wird von main.cpp beim Bildschirm-Timeout (screenDimmed) auf + // Config::ECO_FETCH_INTERVAL_MS und beim Aufwachen wieder auf + // Config::FETCH_INTERVAL_MS gesetzt. + void setFetchInterval(uint32_t ms); } \ No newline at end of file diff --git a/src/settings_store.cpp b/src/settings_store.cpp index d15d7c3..077a87f 100644 --- a/src/settings_store.cpp +++ b/src/settings_store.cpp @@ -25,6 +25,7 @@ namespace { bool nightDimmingOn = true; bool screensaverOn = false; bool hideGroundVehiclesOn = true; + bool ecoModeOn = false; uint8_t languageIdx = 0; uint8_t unitsModeVal = 0; @@ -68,8 +69,10 @@ if (key == "range_index") { nightDimmingOn = (value.toInt() != 0); } else if (key == "screensaver") { screensaverOn = (value.toInt() != 0); - } else if (key == "hide_ground_vehicles") { +} else if (key == "hide_ground_vehicles") { hideGroundVehiclesOn = (value.toInt() != 0); + } else if (key == "eco_mode") { + ecoModeOn = (value.toInt() != 0); } else if (key == "language") { int v = value.toInt(); if (v >= 0 && v <= 5) languageIdx = (uint8_t)v; @@ -134,6 +137,7 @@ void save() { f.printf("night_dimming=%d\n", nightDimmingOn ? 1 : 0); f.printf("screensaver=%d\n", screensaverOn ? 1 : 0); f.printf("hide_ground_vehicles=%d\n", hideGroundVehiclesOn ? 1 : 0); + f.printf("eco_mode=%d\n", ecoModeOn ? 1 : 0); f.printf("language=%d\n", languageIdx); f.printf("units_mode=%d\n", unitsModeVal); f.close(); @@ -253,6 +257,13 @@ void setHideGroundVehicles(bool on) { save(); } +bool ecoModeEnabled() { return ecoModeOn; } + +void setEcoModeEnabled(bool on) { + ecoModeOn = on; + save(); +} + uint8_t language() { return languageIdx; } void setLanguage(uint8_t lang) { diff --git a/src/settings_store.h b/src/settings_store.h index 5b49682..ea65833 100644 --- a/src/settings_store.h +++ b/src/settings_store.h @@ -59,9 +59,12 @@ uint8_t rangeIndex(); bool screensaverEnabled(); void setScreensaverEnabled(bool on); - bool hideGroundVehicles(); +bool hideGroundVehicles(); void setHideGroundVehicles(bool on); + bool ecoModeEnabled(); + void setEcoModeEnabled(bool on); + // Sprache der Benutzeroberflaeche: 0=EN,1=DE,2=FR,3=TR,4=ES,5=IT. uint8_t language(); void setLanguage(uint8_t lang);