From b740574c681be5a8f62f7630817c125a8d89e839 Mon Sep 17 00:00:00 2001 From: Empire Date: Thu, 16 Apr 2026 20:42:08 +0200 Subject: [PATCH] refactor: add timezone support to `wait_infinity`, improve MQTT updates in config mode, and minor cleanup --- .../rust/src/hal/savegame_manager.rs | 6 ++-- .../MainBoard/rust/src/log/interceptor.rs | 3 +- Software/MainBoard/rust/src/main.rs | 33 +++++++++++++++---- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Software/MainBoard/rust/src/hal/savegame_manager.rs b/Software/MainBoard/rust/src/hal/savegame_manager.rs index 172df5a..92ff03f 100644 --- a/Software/MainBoard/rust/src/hal/savegame_manager.rs +++ b/Software/MainBoard/rust/src/hal/savegame_manager.rs @@ -2,7 +2,7 @@ use alloc::vec::Vec; use bincode::{Decode, Encode}; use embedded_savegame::storage::{Flash, Storage}; use embedded_storage::nor_flash::{NorFlash, ReadNorFlash}; -use esp_bootloader_esp_idf::partitions::{Error as PartitionError, Error, FlashRegion}; +use esp_bootloader_esp_idf::partitions::{Error as PartitionError, FlashRegion}; use log::{error, info}; use serde::Serialize; @@ -64,8 +64,8 @@ impl Flash for SavegameFlashAdapter<'_> { data.len() ); let error = NorFlash::write(self.region, addr, data); - if error.is_err() { - error!("error {:?}", error.unwrap_err()) + if let Err(err) = error { + error!("error {:?}", err); } error.map_err(SavegameFlashError) } diff --git a/Software/MainBoard/rust/src/log/interceptor.rs b/Software/MainBoard/rust/src/log/interceptor.rs index 196ebbd..62611df 100644 --- a/Software/MainBoard/rust/src/log/interceptor.rs +++ b/Software/MainBoard/rust/src/log/interceptor.rs @@ -34,8 +34,7 @@ impl InterceptorLogger { } pub fn init(&'static self) { - match log::set_logger(self) - .map(|()| log::set_max_level(LevelFilter::Info)) { + match log::set_logger(self).map(|()| log::set_max_level(LevelFilter::Info)) { Ok(()) => {} Err(e) => { error!("Logger already set: {}", e); diff --git a/Software/MainBoard/rust/src/main.rs b/Software/MainBoard/rust/src/main.rs index c028d51..2d63e90 100644 --- a/Software/MainBoard/rust/src/main.rs +++ b/Software/MainBoard/rust/src/main.rs @@ -239,7 +239,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { println!("starting webserver"); let _ = http_server(reboot_now.clone(), stack); - wait_infinity(board, WaitType::MissingConfig, reboot_now.clone()).await; + wait_infinity(board, WaitType::MissingConfig, reboot_now.clone(), UTC).await; } let mut stack: OptionLock = OptionLock::empty(); @@ -276,7 +276,6 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { }), None => UTC, // Fallback to UTC if no timezone is set }; - let _timezone = UTC; let timezone_time = cur.with_timezone(&timezone); info!( @@ -321,7 +320,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { } else { bail!("Network stack missing, hard abort") } - wait_infinity(board, WaitType::ConfigButton, reboot_now.clone()).await; + wait_infinity(board, WaitType::ConfigButton, reboot_now.clone(), timezone).await; } else { log(LogMessage::NormalRun, 0, 0, "", ""); } @@ -578,19 +577,18 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { .mqtt_publish("/deepsleep", "night 1h").await; 60 }; + let _ = board .board_hal .get_esp() .mqtt_publish("/state", "sleep") .await; - info!("Go to sleep for {deep_sleep_duration_minutes} minutes"); + //determine next event //is light out of work trigger soon? //is battery low ?? //is deep sleep - //TODO - //mark_app_valid(); let stay_alive = MQTT_STAY_ALIVE.load(Ordering::Relaxed); info!("Check stay alive, current state is {stay_alive}"); @@ -599,7 +597,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { let reboot_now = Arc::new(AtomicBool::new(false)); if let Some(s) = stack.take() { spawner.spawn(http_server(reboot_now.clone(), s))?; - wait_infinity(board, WaitType::MqttConfig, reboot_now.clone()).await; + wait_infinity(board, WaitType::MqttConfig, reboot_now.clone(), timezone).await; } else { bail!("Network Stack missing, hard abort"); } @@ -740,6 +738,9 @@ pub async fn do_secure_pump( Timer::after(sleep_time).await; pump_time_ms += 50; } + } else { + //noticable dummy value + pump_time_ms = 1337; } board.board_hal.get_tank_sensor()?.stop_flow_meter(); let final_flow_value = board.board_hal.get_tank_sensor()?.get_flow_meter_value(); @@ -975,6 +976,7 @@ async fn wait_infinity( board: MutexGuard<'_, CriticalSectionRawMutex, HAL<'static>>, wait_type: WaitType, reboot_now: Arc, + timezone: Tz, ) -> ! { //since we force to have the lock when entering, we can release it to ensure the caller does not forget to dispose of it drop(board); @@ -984,6 +986,7 @@ async fn wait_infinity( let mut pattern_step = 0; let serial_config_receive = AtomicBool::new(false); let mut suppress_further_mppt_error = false; + let mut last_mqtt_update: Option = None; // Long-press exit (for webserver config modes): hold boot button for 5 seconds. let mut exit_hold_started: Option = None; @@ -1060,6 +1063,22 @@ async fn wait_infinity( } } + // MQTT updates in config mode + let now = Instant::now(); + if last_mqtt_update.is_none() + || now.duration_since(last_mqtt_update.unwrap_or(Instant::from_secs(0))) + >= Duration::from_secs(60) + { + let cur = board.board_hal.get_time().await; + let timezone_time = cur.with_timezone(&timezone); + + let esp = board.board_hal.get_esp(); + esp.mqtt_publish("/firmware/state", "config").await; + esp.mqtt_publish("/firmware/last_online", &timezone_time.to_rfc3339()) + .await; + last_mqtt_update = Some(now); + } + // Skip default blink code when a progress display is active if !PROGRESS_ACTIVE.load(Ordering::Relaxed) { match wait_type {