From 2497891c4d325c2140d5f0ec48638787641d26a5 Mon Sep 17 00:00:00 2001 From: ju6ge Date: Thu, 20 Feb 2025 21:26:30 +0100 Subject: [PATCH 1/8] uncomment npm calls in build.rs --- rust/build.rs | 64 +++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/rust/build.rs b/rust/build.rs index b0169e5..f970efe 100644 --- a/rust/build.rs +++ b/rust/build.rs @@ -3,39 +3,39 @@ use std::process::Command; use vergen::EmitBuilder; fn main() { println!("cargo:rerun-if-changed=./src/src_webpack"); - Command::new("rm") - .arg("./src/webserver/bundle.js") - .output() - .unwrap(); + //Command::new("rm") + //.arg("./src/webserver/bundle.js") + //.output() + //.unwrap(); - match Command::new("cmd").spawn() { - Ok(_) => { - println!("Assuming build on windows"); - let output = Command::new("cmd") - .arg("/K") - .arg("npx") - .arg("webpack") - .current_dir("./src_webpack") - .output() - .unwrap(); - println!("status: {}", output.status); - println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); - println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); - assert!(output.status.success()); - } - Err(_) => { - println!("Assuming build on linux"); - let output = Command::new("npx") - .arg("webpack") - .current_dir("./src_webpack") - .output() - .unwrap(); - println!("status: {}", output.status); - println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); - println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); - assert!(output.status.success()); - } - } + //match Command::new("cmd").spawn() { + //Ok(_) => { + //println!("Assuming build on windows"); + //let output = Command::new("cmd") + //.arg("/K") + //.arg("npx") + //.arg("webpack") + //.current_dir("./src_webpack") + //.output() + //.unwrap(); + //println!("status: {}", output.status); + //println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + //println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + //assert!(output.status.success()); + //} + //Err(_) => { + //println!("Assuming build on linux"); + //let output = Command::new("npx") + //.arg("webpack") + //.current_dir("./src_webpack") + //.output() + //.unwrap(); + //println!("status: {}", output.status); + //println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + //println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + //assert!(output.status.success()); + //} + //} embuild::espidf::sysenv::output(); let _ = EmitBuilder::builder().all_git().all_build().emit(); From 5c13715981fa29ea7cd00edd49142ab6df1addf3 Mon Sep 17 00:00:00 2001 From: ju6ge Date: Thu, 27 Feb 2025 21:30:58 +0100 Subject: [PATCH 2/8] document PlantState struct and add TODO notes --- rust/src/main.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/rust/src/main.rs b/rust/src/main.rs index be5165a..d35aec3 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -71,23 +71,42 @@ struct LightState { } #[derive(Debug, PartialEq, Default)] +/// State of a single plant to be tracked +/// +/// TODO can some state be replaced with functions +/// TODO unify with PlantStateMQTT struct PlantState { + /// state of humidity sensor on bank a a: Option, + /// raw measured frequency value for sensor on bank a in hertz a_raw: Option, + /// state of humidity sensor on bank b b: Option, + /// raw measured frequency value for sensor on bank b in hertz b_raw: Option, + /// how often has the logic determined that plant should have been irrigated but wasn't consecutive_pump_count: u32, - after_p: Option, + /// plant needs to be watered do_water: bool, + /// is plant considerd to be dry according to settings dry: bool, + /// is pump currently running active: bool, + /// TODO: convert this to an Option enum for every case that can happen pump_error: bool, + /// if pump count has increased higher than configured limit not_effective: bool, + /// plant irrigation cooldown is active cooldown: bool, + /// we want to irrigate but tank is empty no_water: bool, + ///TODO: combine with field a using Result sensor_error_a: Option, + ///TODO: combine with field b using Result sensor_error_b: Option, + /// pump should not be watered at this time of day out_of_work_hour: bool, + /// next time when pump should activate next_pump: Option>, } From 12d902730fa4743255a10ec14671fb32dbf79afa Mon Sep 17 00:00:00 2001 From: ju6ge Date: Thu, 27 Feb 2025 21:34:47 +0100 Subject: [PATCH 3/8] document Light State enum --- rust/src/main.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/rust/src/main.rs b/rust/src/main.rs index d35aec3..07ecfe4 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -63,10 +63,15 @@ enum WaitType { } #[derive(Serialize, Deserialize, Debug, PartialEq, Default)] +/// Light State tracking data for mqtt struct LightState { + /// led is on active: bool, + /// led should not be on at this time of day out_of_work_hour: bool, + /// battery is low so do not use led battery_low: bool, + /// the sun is up is_day: bool, } From ccd2e2d98a18e3239a6f49bdba0b8768e93194c7 Mon Sep 17 00:00:00 2001 From: ju6ge Date: Thu, 27 Feb 2025 21:44:02 +0100 Subject: [PATCH 4/8] improve WaitType blink_pattern selection (code readability) --- rust/src/main.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/rust/src/main.rs b/rust/src/main.rs index 07ecfe4..d1fbf6b 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -62,6 +62,17 @@ enum WaitType { MqttConfig, } +impl WaitType { + fn blink_pattern(&self) -> u32 { + match self { + WaitType::MissingConfig => 500_u32, + WaitType::ConfigButton => 100_u32, + WaitType::MqttConfig => 200_u32, + } + } +} + + #[derive(Serialize, Deserialize, Debug, PartialEq, Default)] /// Light State tracking data for mqtt struct LightState { @@ -917,15 +928,12 @@ fn update_plant_state( } fn wait_infinity(wait_type: WaitType, reboot_now: Arc) -> ! { - let delay = match wait_type { - WaitType::MissingConfig => 500_u32, - WaitType::ConfigButton => 100_u32, - WaitType::MqttConfig => 200_u32, - }; + let delay = wait_type.blink_pattern(); + let mut led_count = 8; loop { if wait_type == WaitType::MissingConfig { - led_count = led_count + 1; + led_count += 1; if led_count > 8 { led_count = 1; } From 45a088ca78fef6164b3dae66ccf0815eb27378b7 Mon Sep 17 00:00:00 2001 From: ju6ge Date: Thu, 27 Feb 2025 21:58:30 +0100 Subject: [PATCH 5/8] simply wait loop logic --- rust/src/main.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/rust/src/main.rs b/rust/src/main.rs index d1fbf6b..9e462fa 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -932,11 +932,10 @@ fn wait_infinity(wait_type: WaitType, reboot_now: Arc) -> ! { let mut led_count = 8; loop { + // TODO implement actually different blink patterns instead of modulating blink duration if wait_type == WaitType::MissingConfig { + led_count %= 8; led_count += 1; - if led_count > 8 { - led_count = 1; - } }; unsafe { //do not trigger watchdog @@ -946,17 +945,14 @@ fn wait_infinity(wait_type: WaitType, reboot_now: Arc) -> ! { BOARD_ACCESS.lock().unwrap().general_fault(true); vTaskDelay(delay); BOARD_ACCESS.lock().unwrap().general_fault(false); + //TODO move locking outside of loop and drop afterwards for i in 0..8 { BOARD_ACCESS.lock().unwrap().fault(i, false); } vTaskDelay(delay); - match wait_type { - WaitType::MissingConfig => {} - WaitType::ConfigButton => {} - WaitType::MqttConfig => { - if !STAY_ALIVE.load(std::sync::atomic::Ordering::Relaxed) { - reboot_now.store(true, std::sync::atomic::Ordering::Relaxed); - } + if wait_type == WaitType::MqttConfig { + if !STAY_ALIVE.load(std::sync::atomic::Ordering::Relaxed) { + reboot_now.store(true, std::sync::atomic::Ordering::Relaxed); } } if reboot_now.load(std::sync::atomic::Ordering::Relaxed) { From 270d39c751c13492f031a080ff1029b93e866579 Mon Sep 17 00:00:00 2001 From: ju6ge Date: Thu, 27 Feb 2025 22:05:59 +0100 Subject: [PATCH 6/8] document more types in main.rs --- rust/src/main.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/rust/src/main.rs b/rust/src/main.rs index 9e462fa..ff83ff3 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -127,6 +127,7 @@ struct PlantState { } #[derive(Serialize, Deserialize, Debug, PartialEq)] +/// humidity sensor error enum SensorError { Unknown, ShortCircuit { hz: f32, max: f32 }, @@ -134,13 +135,23 @@ enum SensorError { } #[derive(Debug, PartialEq, Default)] +/// State data for water tank +/// +/// TODO unify with TankStateMQTT struct TankState { + /// is there enough water in the tank enough_water: bool, + /// warning that water needs to be refilled soon warn_level: bool, + /// estimation how many ml are still in tank left_ml: u32, + /// if there is was an issue with the water level sensor + /// TODO merge with left_ml as Result sensor_error: bool, + /// raw water sensor value raw: u16, } + #[derive(Serialize)] struct TankStateMQTT { enough_water: bool, From 818b708ee333c55413aa59899adf45c54e528b89 Mon Sep 17 00:00:00 2001 From: ju6ge Date: Thu, 27 Feb 2025 22:13:50 +0100 Subject: [PATCH 7/8] document entry point --- rust/src/main.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rust/src/main.rs b/rust/src/main.rs index ff83ff3..7eae48a 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -978,16 +978,18 @@ fn wait_infinity(wait_type: WaitType, reboot_now: Arc) -> ! { fn main() { let result = safe_main(); match result { + // this should not get triggered, safe_main should not return but go into deep sleep with sensbile + // timeout, this is just a fallback Ok(_) => { println!("Main app finished, restarting"); BOARD_ACCESS.lock().unwrap().set_restart_to_conf(false); BOARD_ACCESS.lock().unwrap().deep_sleep(1); } + // if safe_main exists with error, rollback to known good ota version Err(err) => { println!("Failed main {}", err); let rollback_successful = rollback_and_reboot(); - println!("Failed to rollback :("); - rollback_successful.unwrap(); + panic!("Failed to rollback :("); } } } From 080028dd0a588e255c1e54bffb8d7af1f8985012 Mon Sep 17 00:00:00 2001 From: ju6ge Date: Thu, 27 Feb 2025 22:44:19 +0100 Subject: [PATCH 8/8] more idiomatic current_time determination --- rust/src/main.rs | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/rust/src/main.rs b/rust/src/main.rs index 7eae48a..4bb6f2b 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -242,23 +242,15 @@ fn safe_main() -> anyhow::Result<()> { log(log::LogMessage::FilesystemMount, free_space.free_size as u32, free_space.total_size as u32, &free_space.used_size.to_string(), ""); + let mut cur = board.get_rtc_time().or_else(|err| { + println!("rtc module error: {:?}", err); + board.general_fault(true); + board.time() + }).map_err(|err| -> Result<(), _>{ + bail!("time error {}", err); + }).unwrap(); - let mut cur = match board.get_rtc_time() { - Ok(time) => time, - Err(err) => { - println!("rtc module error: {}", err); - board.general_fault(true); - let time = board.time(); - match time { - Ok(cur) => cur, - Err(err) => { - bail!("time error {}", err); - } - } - } - }; - - //check if we know the time current > 2020 + //check if we know the time current > 2020 (plausibility check, this code is newer than 2020) if cur.year() < 2020 { to_config = true; log(log::LogMessage::YearInplausibleForceConfig, 0,0,"",""); @@ -988,7 +980,7 @@ fn main() { // if safe_main exists with error, rollback to known good ota version Err(err) => { println!("Failed main {}", err); - let rollback_successful = rollback_and_reboot(); + let _rollback_successful = rollback_and_reboot(); panic!("Failed to rollback :("); } }