From a2abc9927531114409ad9fb6411f2ea5f2aa5c42 Mon Sep 17 00:00:00 2001 From: Empire Phoenix Date: Sat, 30 May 2026 20:57:39 +0200 Subject: [PATCH] Refactor formatting and remove unused imports in mqtt and plant_state modules --- Software/MainBoard/rust/src/fat_error.rs | 2 +- Software/MainBoard/rust/src/hal/battery.rs | 5 +- Software/MainBoard/rust/src/hal/esp.rs | 21 +++-- Software/MainBoard/rust/src/hal/water.rs | 8 +- .../MainBoard/rust/src/log/interceptor.rs | 3 +- Software/MainBoard/rust/src/main.rs | 56 ++++++++---- Software/MainBoard/rust/src/mqtt.rs | 19 ++-- Software/MainBoard/rust/src/network.rs | 35 ++++---- Software/MainBoard/rust/src/plant_state.rs | 86 +++++++++---------- Software/MainBoard/rust/src/tank.rs | 16 ++-- .../MainBoard/rust/src/webserver/get_json.rs | 6 +- Software/MainBoard/rust/src/webserver/mod.rs | 6 +- 12 files changed, 143 insertions(+), 120 deletions(-) diff --git a/Software/MainBoard/rust/src/fat_error.rs b/Software/MainBoard/rust/src/fat_error.rs index 68dcda1..c45e916 100644 --- a/Software/MainBoard/rust/src/fat_error.rs +++ b/Software/MainBoard/rust/src/fat_error.rs @@ -316,7 +316,7 @@ impl From for FatError { impl From for FatError { fn from(value: BmsProtocolError) -> Self { match value { - BmsProtocolError::I2cCommunicationError =>FatError::String { + BmsProtocolError::I2cCommunicationError => FatError::String { error: "I2C communication error".to_string(), }, BmsProtocolError::ChecksumError => FatError::String { diff --git a/Software/MainBoard/rust/src/hal/battery.rs b/Software/MainBoard/rust/src/hal/battery.rs index fd05964..ba67601 100644 --- a/Software/MainBoard/rust/src/hal/battery.rs +++ b/Software/MainBoard/rust/src/hal/battery.rs @@ -81,7 +81,8 @@ impl BatteryInteraction for WCHI2CSlave<'_> { let state_of_charge = state.remaining_capacity_mah as f32 * 100. / state.lifetime_capacity_mah as f32; - let state_of_health = state.lifetime_capacity_mah as f32 / config.capacity_mah as f32 * 100.; + let state_of_health = + state.lifetime_capacity_mah as f32 / config.capacity_mah as f32 * 100.; Ok(BatteryState::Info(BatteryInfo { voltage_mv: Some(state.current_mv), @@ -91,7 +92,7 @@ impl BatteryInteraction for WCHI2CSlave<'_> { soc_pct: Some(state_of_charge), soh_pct: Some(state_of_health), temperature_c: Some(state.temperature_celcius), - error: None + error: None, })) } diff --git a/Software/MainBoard/rust/src/hal/esp.rs b/Software/MainBoard/rust/src/hal/esp.rs index b502474..6444b42 100644 --- a/Software/MainBoard/rust/src/hal/esp.rs +++ b/Software/MainBoard/rust/src/hal/esp.rs @@ -1,5 +1,5 @@ use crate::bail; -use crate::config::{PlantControllerConfig}; +use crate::config::PlantControllerConfig; use crate::hal::savegame_manager::SavegameManager; use crate::hal::PLANT_COUNT; use crate::log::{log, LogMessage}; @@ -16,7 +16,6 @@ use embedded_storage::nor_flash::{check_erase, NorFlash, ReadNorFlash, RmwNorFla use esp_bootloader_esp_idf::ota::OtaImageState::Valid; use esp_bootloader_esp_idf::ota::{Ota, OtaImageState}; use esp_bootloader_esp_idf::partitions::{AppPartitionSubType, FlashRegion}; -use serde::{Deserialize, Serialize}; use esp_hal::gpio::{Input, RtcPinWithResistors}; use esp_hal::rng::Rng; use esp_hal::rtc_cntl::{ @@ -26,10 +25,11 @@ use esp_hal::rtc_cntl::{ use esp_hal::system::software_reset; use esp_hal::uart::Uart; use esp_hal::Blocking; -use esp_radio::wifi::ap::{AccessPointInfo}; +use esp_radio::wifi::ap::AccessPointInfo; use esp_radio::wifi::scan::{ScanConfig, ScanTypeConfig}; use esp_radio::wifi::{Interface, WifiController}; use log::{error, info}; +use serde::{Deserialize, Serialize}; /// Detailed Wi-Fi scan information including signal strength #[derive(Serialize, Deserialize, Debug, Clone)] @@ -45,11 +45,15 @@ pub struct WifiScanDetails { fn format_bssid(bssid: &[u8; 6]) -> String { alloc::format!( "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}", - bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5] + bssid[0], + bssid[1], + bssid[2], + bssid[3], + bssid[4], + bssid[5] ) } - #[esp_hal::ram(unstable(rtc_fast), unstable(persistent))] static mut LAST_WATERING_TIMESTAMP: [i64; PLANT_COUNT] = [0; PLANT_COUNT]; #[esp_hal::ram(unstable(rtc_fast), unstable(persistent))] @@ -214,7 +218,7 @@ impl Esp<'_> { /// Return detailed Wi-Fi scan information including signal strength pub(crate) async fn wifi_scan_details(&mut self) -> FatResult> { let ap_infos = self.wifi_scan().await?; - + // Convert AccessPointInfo to WifiScanDetails let details: Vec = ap_infos .iter() @@ -223,10 +227,10 @@ impl Esp<'_> { bssid: format_bssid(&ap.bssid), rssi: ap.signal_strength as i32, channel: ap.channel as u8, - auth_method: format!("{:?}",ap.auth_method), + auth_method: format!("{:?}", ap.auth_method), }) .collect(); - + Ok(details) } @@ -414,5 +418,4 @@ impl Esp<'_> { } } } - } diff --git a/Software/MainBoard/rust/src/hal/water.rs b/Software/MainBoard/rust/src/hal/water.rs index 3aeffd6..b826177 100644 --- a/Software/MainBoard/rust/src/hal/water.rs +++ b/Software/MainBoard/rust/src/hal/water.rs @@ -7,7 +7,7 @@ use esp_hal::delay::Delay; use esp_hal::gpio::{DriveMode, Flex, Input, InputConfig, Output, OutputConfig, Pull}; use esp_hal::pcnt::channel::CtrlMode::Keep; use esp_hal::pcnt::channel::EdgeMode::{Hold, Increment}; -use esp_hal::pcnt::unit::{Unit}; +use esp_hal::pcnt::unit::Unit; use esp_hal::peripherals::GPIO5; use esp_hal::Async; use log::{error, info}; @@ -145,7 +145,11 @@ impl<'a> TankSensor<'a> { water_temp_sensor = Some(device); break; } else { - info!("OneWire: skipping device — not a DS18B20 (family 0x{:02X} != 0x{:02X})", device.address[0], ds18b20::FAMILY_CODE); + info!( + "OneWire: skipping device — not a DS18B20 (family 0x{:02X} != 0x{:02X})", + device.address[0], + ds18b20::FAMILY_CODE + ); } } if devices_found == 0 { diff --git a/Software/MainBoard/rust/src/log/interceptor.rs b/Software/MainBoard/rust/src/log/interceptor.rs index d45f91c..94fc7db 100644 --- a/Software/MainBoard/rust/src/log/interceptor.rs +++ b/Software/MainBoard/rust/src/log/interceptor.rs @@ -32,7 +32,8 @@ impl LiveLogBuffer { match after { None => (self.entries.clone(), false, next_seq), Some(after_seq) => { - let result: Vec<_> = self.entries + let result: Vec<_> = self + .entries .iter() .filter(|(seq, _)| *seq > after_seq) .cloned() diff --git a/Software/MainBoard/rust/src/main.rs b/Software/MainBoard/rust/src/main.rs index d1e0e51..7ddd927 100644 --- a/Software/MainBoard/rust/src/main.rs +++ b/Software/MainBoard/rust/src/main.rs @@ -14,9 +14,9 @@ esp_bootloader_esp_idf::esp_app_desc!(); use esp_backtrace as _; -use crate::hal::PROGRESS_ACTIVE; use crate::config::{PlantConfig, PlantControllerConfig}; use crate::fat_error::{ContextExt, FatResult}; +use crate::hal::PROGRESS_ACTIVE; use crate::log::log; use crate::tank::{determine_tank_state, TankError, WATER_FROZEN_THRESH}; @@ -42,8 +42,8 @@ use embassy_sync::once_lock::OnceLock; use embassy_time::{Duration, Instant, Timer}; use esp_hal::rom::ets_delay_us; use esp_hal::system::software_reset; -use esp_println::{println}; -use hal::battery::{BatteryState}; +use esp_println::println; +use hal::battery::BatteryState; use log::LogMessage; use option_lock::OptionLock; use plant_state::PlantState; @@ -123,8 +123,6 @@ pub struct PumpResult { overcurrent_ma: Option, } - - async fn safe_main(spawner: Spawner) -> FatResult<()> { info!("Startup Rust"); @@ -208,10 +206,15 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { info!("No wifi configured, starting initial config mode"); let esp = board.board_hal.get_esp(); - let ssid = esp.load_config().await + let ssid = esp + .load_config() + .await .map(|config| config.network.ap_ssid.to_string()) .unwrap_or_else(|_| String::from("PlantCtrl Emergency Mode")); - let device = esp.interface_ap.take().context("AP interface already taken")?; + let device = esp + .interface_ap + .take() + .context("AP interface already taken")?; let stack = network::wifi_ap(ssid, device, &esp.controller, &mut esp.rng, spawner).await?; let reboot_now = Arc::new(AtomicBool::new(false)); @@ -228,7 +231,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { info!("No wifi configured"); //the current sensors require this amount to stabilize, in the case of Wi-Fi this is already handled due to connect timings; Timer::after_millis(100).await; - network::NetworkMode::OFFLINE + network::NetworkMode::OFFLINE }; if matches!(network_mode, network::NetworkMode::OFFLINE) && to_config { @@ -236,14 +239,18 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { let res = { let esp = board.board_hal.get_esp(); - let ssid = esp.load_config().await + let ssid = esp + .load_config() + .await .map(|config| config.network.ap_ssid.to_string()) .unwrap_or_else(|_| String::from("PlantCtrl Emergency Mode")); let device = match esp.interface_ap.take() { Some(d) => d, None => { use crate::fat_error::FatError; - return Err(FatError::String { error: "AP interface already taken".to_string() }); + return Err(FatError::String { + error: "AP interface already taken".to_string(), + }); } }; network::wifi_ap(ssid, device, &esp.controller, &mut esp.rng, spawner).await @@ -276,9 +283,11 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { if let network::NetworkMode::WIFI { ref ip_address, .. } = network_mode { mqtt::publish_firmware_info(version, ip_address, &timezone_time.to_rfc3339()).await; - mqtt::publish_battery_state(&mut board).await.unwrap_or_else(|e| { - error!("Error publishing battery state {e}"); - }); + mqtt::publish_battery_state(&mut board) + .await + .unwrap_or_else(|e| { + error!("Error publishing battery state {e}"); + }); let _ = mqtt::publish_mppt_state(&mut board).await; let _ = mqtt::publish_wifi_scan(&mut board).await; } @@ -325,7 +334,9 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { if let Some(err) = tank_state.got_error(&board.board_hal.get_config().tank) { match err { TankError::SensorDisabled => { /* unreachable */ } - TankError::SensorMissing { raw_mv: raw_value_mv } => log( + TankError::SensorMissing { + raw_mv: raw_value_mv, + } => log( LogMessage::TankSensorMissing, raw_value_mv as u32, 0, @@ -355,7 +366,11 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { } let mut water_frozen = false; - let water_temp: FatResult = board.board_hal.get_tank_sensor().water_temperature_c().await; + let water_temp: FatResult = board + .board_hal + .get_tank_sensor() + .water_temperature_c() + .await; if let Ok(res) = water_temp { if res < WATER_FROZEN_THRESH { @@ -581,11 +596,15 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { light_state.battery_low = false; } BatteryState::Info(data) => { - if data.soc_pct.is_some_and(|soc| soc < board.board_hal.get_config().night_lamp.low_soc_cutoff as f32) { + if data.soc_pct.is_some_and(|soc| { + soc < board.board_hal.get_config().night_lamp.low_soc_cutoff as f32 + }) { board.board_hal.get_esp().set_low_voltage_in_cycle(); info!("Set low voltage in cycle"); } - if data.soc_pct.is_some_and(|soc| soc > board.board_hal.get_config().night_lamp.low_soc_restore as f32) { + if data.soc_pct.is_some_and(|soc| { + soc > board.board_hal.get_config().night_lamp.low_soc_restore as f32 + }) { board.board_hal.get_esp().clear_low_voltage_in_cycle(); info!("Clear low voltage in cycle"); } @@ -988,8 +1007,7 @@ async fn wait_infinity( let timezone_time = cur.with_timezone(&timezone); mqtt::publish("/state", "config").await; - mqtt::publish("/firmware/last_online", &timezone_time.to_rfc3339()) - .await; + mqtt::publish("/firmware/last_online", &timezone_time.to_rfc3339()).await; last_mqtt_update = Some(now); } diff --git a/Software/MainBoard/rust/src/mqtt.rs b/Software/MainBoard/rust/src/mqtt.rs index 0249c27..ebcf21b 100644 --- a/Software/MainBoard/rust/src/mqtt.rs +++ b/Software/MainBoard/rust/src/mqtt.rs @@ -288,11 +288,7 @@ pub async fn publish_plant_states( Ok(()) } -pub async fn publish_firmware_info( - version: VersionInfo, - ip_address: &str, - timezone_time: &str, -) { +pub async fn publish_firmware_info(version: VersionInfo, ip_address: &str, timezone_time: &str) { publish("/firmware/address", ip_address).await; let version = &serde_json::to_string(&version); match version { @@ -384,12 +380,7 @@ pub async fn publish_mppt_state( pub async fn publish_battery_state( board: &mut MutexGuard<'_, CriticalSectionRawMutex, HAL<'static>>, ) -> FatResult<()> { - let telemetry = match board - .board_hal - .get_battery_monitor() - .get_state() - .await - { + let telemetry = match board.board_hal.get_battery_monitor().get_state().await { Ok(BatteryState::Info(info)) => info, Ok(BatteryState::Unknown) => BatteryInfo { voltage_mv: None, @@ -414,7 +405,7 @@ pub async fn publish_battery_state( }), }, }; - let json = serde_json::to_string(&telemetry)?; + let json = serde_json::to_string(&telemetry)?; publish("/battery", &json).await; Ok(()) } @@ -424,10 +415,10 @@ pub async fn publish_wifi_scan( board: &mut MutexGuard<'_, CriticalSectionRawMutex, HAL<'static>>, ) -> FatResult<()> { let mut wifi_details = board.board_hal.get_esp().wifi_scan_details().await?; - + // Sort by RSSI in descending order (strongest first) wifi_details.sort_by(|a, b| b.rssi.cmp(&a.rssi)); - + // Take only the strongest 10 results let wifi_results: Vec = wifi_details .iter() diff --git a/Software/MainBoard/rust/src/network.rs b/Software/MainBoard/rust/src/network.rs index 80dac32..b59502d 100644 --- a/Software/MainBoard/rust/src/network.rs +++ b/Software/MainBoard/rust/src/network.rs @@ -1,13 +1,19 @@ use crate::bail; use crate::config::NetworkConfig; use crate::fat_error::{ContextExt, FatError, FatResult}; -use crate::hal::{HAL}; +use crate::hal::HAL; use crate::mqtt; use crate::util::mk_static; use alloc::string::{String, ToString}; use alloc::sync::Arc; use chrono::{DateTime, Utc}; use core::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4}; +use edge_dhcp::{ + io::{self, DEFAULT_SERVER_PORT}, + server::{Server, ServerOptions}, +}; +use edge_nal::UdpBind; +use edge_nal_embassy::{Udp, UdpBuffers}; use embassy_executor::Spawner; use embassy_net::dns::DnsQueryType; use embassy_net::udp::{PacketMetadata, UdpSocket}; @@ -15,21 +21,15 @@ use embassy_net::{DhcpConfig, Runner, Stack, StackResources, StaticConfigV4}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::mutex::{Mutex, MutexGuard}; use embassy_time::{Duration, Timer, WithTimeout}; -use option_lock::OptionLock; -use edge_dhcp::{ - io::{self, DEFAULT_SERVER_PORT}, - server::{Server, ServerOptions}, -}; -use edge_nal::UdpBind; -use edge_nal_embassy::{Udp, UdpBuffers}; use esp_hal::rng::Rng; use esp_println::println; use esp_radio::wifi::ap::AccessPointConfig; use esp_radio::wifi::sta::StationConfig; use esp_radio::wifi::{AuthenticationMethod, Config, Interface}; -use log::{info, warn, error}; +use log::{error, info, warn}; +use option_lock::OptionLock; use serde::Serialize; -use sntpc::{NtpContext, NtpTimestampGenerator, NtpUdpSocket, get_time}; +use sntpc::{get_time, NtpContext, NtpTimestampGenerator, NtpUdpSocket}; const NTP_SERVER: &str = "pool.ntp.org"; @@ -225,8 +225,7 @@ pub async fn wifi_ap( ); let stack = mk_static!(Stack, stack); - let client_config = - Config::AccessPoint(AccessPointConfig::default().with_ssid(ssid.clone())); + let client_config = Config::AccessPoint(AccessPointConfig::default().with_ssid(ssid.clone())); controller.lock().await.set_config(&client_config)?; println!("start net task"); @@ -321,7 +320,7 @@ pub async fn wifi( .lock() .await .set_config(&Config::Station(client_config))?; - + match controller .lock() .await @@ -352,7 +351,10 @@ pub async fn wifi( .await; if res.is_err() { - warn!("WiFi connection attempt {} failed: link up timeout", attempts + 1); + warn!( + "WiFi connection attempt {} failed: link up timeout", + attempts + 1 + ); attempts += 1; Timer::after(Duration::from_millis(500)).await; continue; @@ -368,7 +370,10 @@ pub async fn wifi( .await; if res.is_err() { - warn!("WiFi connection attempt {} failed: config up timeout", attempts + 1); + warn!( + "WiFi connection attempt {} failed: config up timeout", + attempts + 1 + ); attempts += 1; Timer::after(Duration::from_millis(500)).await; continue; diff --git a/Software/MainBoard/rust/src/plant_state.rs b/Software/MainBoard/rust/src/plant_state.rs index bdd1ae9..b7e3c46 100644 --- a/Software/MainBoard/rust/src/plant_state.rs +++ b/Software/MainBoard/rust/src/plant_state.rs @@ -5,7 +5,6 @@ use crate::{config::PlantConfig, hal::HAL, in_time_range}; use chrono::{DateTime, TimeDelta, Utc}; use chrono_tz::Tz; use serde::{Deserialize, Serialize}; -use crate::config::SensorCombineMode; const MOIST_SENSOR_MAX_FREQUENCY: f32 = 160000.; // 160kHz -> very wet const MOIST_SENSOR_MIN_FREQUENCY: f32 = 400.; // this is really, really dry, think like cactus levels @@ -16,7 +15,7 @@ pub enum MoistureSensorError { MissingMessage, NotExpectedMessage { hz: f32 }, ShortCircuit { hz: f32, max: f32 }, - OpenLoop { hz: f32, min: f32 } + OpenLoop { hz: f32, min: f32 }, } #[derive(Debug, PartialEq, Serialize)] @@ -117,20 +116,20 @@ pub struct PlantState { } /// Map sensor frequency to moisture percentage using inverse power-law scaling (quadratic). -/// +/// /// For resistive probes with 555 timer oscillator: /// - Dry soil has high resistance → low oscillation frequency /// - Wet soil has low resistance → high oscillation frequency -/// +/// /// The relationship is non-linear: most frequency change occurs in the wet range. /// Using inverse power-law to give better discrimination at high moisture levels. -/// +/// /// Formula: moisture = (1 - (f_max - f) / (f_max - f_min))^2 * 100 /// = ((f - f_min) / (f_max - f_min))^2 * 100 -/// +/// /// But with k=0.5 (square root) for better high-end discrimination: /// Formula: moisture = sqrt((f - f_min) / (f_max - f_min)) * 100 -/// +/// /// Examples with default range (400-160000 Hz) using k=0.5: /// 400 Hz → 0% (bone dry) /// 10,240 Hz → 25% (dry soil) @@ -158,10 +157,10 @@ fn map_range_moisture( max: max_freq, }); } - + // Normalize to 0-1 range let t = (s - min_freq) / (max_freq - min_freq); - + // Apply power-law mapping with k=0.5 (square root) for better high-moisture discrimination // For resistive probes: frequency ↑ as moisture ↑, but non-linearly // Using sqrt gives more resolution in the wet range (60-160kHz) @@ -229,9 +228,9 @@ impl PlantState { let consecutive_pump_count = board.board_hal.get_esp().consecutive_pump_count(plant_id); let last_fertilizer_timestamp = board.board_hal.get_esp().last_fertilizer_time(plant_id); let (a_builds, b_builds) = board.board_hal.get_sensor_build_minutes(); - + let last_fertilizer_time = DateTime::from_timestamp_millis(last_fertilizer_timestamp); - + // Create plant state first, then check for warnings let state = Self { sensor_a, @@ -245,14 +244,17 @@ impl PlantState { sensor_b_firmware_build_minutes: b_builds[plant_id], last_fertilizer_time, }; - + // Check for sensor warning condition (expected 2 sensors, only 1 responding) - let has_a = state.sensor_a.moisture_percent().is_some() && state.sensor_a.is_err().is_none(); - let has_b = state.sensor_b.moisture_percent().is_some() && state.sensor_b.is_err().is_none(); - + let has_a = + state.sensor_a.moisture_percent().is_some() && state.sensor_a.is_err().is_none(); + let has_b = + state.sensor_b.moisture_percent().is_some() && state.sensor_b.is_err().is_none(); + // Check if we expected two sensors but only got one - let has_sensor_warning = expected_a && expected_b && ((has_a && !has_b) || (!has_a && has_b)); - + let has_sensor_warning = + expected_a && expected_b && ((has_a && !has_b) || (!has_a && has_b)); + // Set fault LED for both errors AND sensor warnings let has_issue = state.is_err() || has_sensor_warning; if has_issue { @@ -279,35 +281,27 @@ impl PlantState { } /// Get combined moisture value with configurable combination mode and sensor warning. - /// + /// /// Returns: /// - Combined moisture percentage (or None if no valid readings) /// - Tuple of errors from sensor A and B /// - Sensor warning indicating if warning LED should be lit (MissingSecondSensor) - pub fn plant_moisture_with_warning( - &self, - plant_conf: &PlantConfig, - ) -> Option - { + pub fn plant_moisture_with_warning(&self, plant_conf: &PlantConfig) -> Option { let moisture = match ( self.sensor_a.moisture_percent(), self.sensor_b.moisture_percent(), ) { - (Some(moisture_a), Some(moisture_b)) => { - match plant_conf.sensor_combine_mode { - SensorCombineMode::Min => Some(moisture_a.min(moisture_b)), - SensorCombineMode::Max => Some(moisture_a.max(moisture_b)), - SensorCombineMode::Avg => Some((moisture_a + moisture_b) / 2.0), - } - } + (Some(moisture_a), Some(moisture_b)) => match plant_conf.sensor_combine_mode { + SensorCombineMode::Min => Some(moisture_a.min(moisture_b)), + SensorCombineMode::Max => Some(moisture_a.max(moisture_b)), + SensorCombineMode::Avg => Some((moisture_a + moisture_b) / 2.0), + }, (Some(moisture), _) => Some(moisture), (_, Some(moisture)) => Some(moisture), _ => None, }; - - - moisture + moisture } pub fn needs_to_be_watered( @@ -344,11 +338,7 @@ impl PlantState { } } - pub fn to_mqtt_info( - &self, - plant_conf: &PlantConfig, - current_time: &DateTime, - ) -> PlantInfo { + pub fn to_mqtt_info(&self, plant_conf: &PlantConfig, current_time: &DateTime) -> PlantInfo { let moisture_pct = self.plant_moisture_with_warning(plant_conf); PlantInfo { moisture_pct, @@ -392,7 +382,9 @@ impl PlantState { } else { None }, - last_fertilizer: self.last_fertilizer_time.map(|t| t.with_timezone(¤t_time.timezone())), + last_fertilizer: self + .last_fertilizer_time + .map(|t| t.with_timezone(¤t_time.timezone())), next_fertilizer: if matches!( plant_conf.mode, PlantWateringMode::TimerOnly @@ -403,7 +395,9 @@ impl PlantState { // Convert to Tz for calculation, then back let tz_last_fert = last_fert.with_timezone(¤t_time.timezone()); tz_last_fert - .checked_add_signed(TimeDelta::minutes(plant_conf.fertilizer_cooldown_min.into())) + .checked_add_signed(TimeDelta::minutes( + plant_conf.fertilizer_cooldown_min.into(), + )) .map(|t| t.with_timezone(¤t_time.timezone())) }) } else { @@ -416,13 +410,11 @@ impl PlantState { fn sensor_to_telemetry(sensor: &MoistureSensorState) -> SensorTelemetry { match sensor { - MoistureSensorState::NoMessage => { - SensorTelemetry { - moisture_pct: None, - raw_hz: None, - error: None - } - } + MoistureSensorState::NoMessage => SensorTelemetry { + moisture_pct: None, + raw_hz: None, + error: None, + }, MoistureSensorState::MoistureValue { hz, moisture_percent, diff --git a/Software/MainBoard/rust/src/tank.rs b/Software/MainBoard/rust/src/tank.rs index 1988240..977f2f7 100644 --- a/Software/MainBoard/rust/src/tank.rs +++ b/Software/MainBoard/rust/src/tank.rs @@ -26,7 +26,9 @@ pub enum TankState { fn raw_voltage_to_divider_percent(raw_value_mv: f32) -> Result { if raw_value_mv > OPEN_TANK_VOLTAGE { - return Err(TankError::SensorMissing { raw_mv: raw_value_mv }); + return Err(TankError::SensorMissing { + raw_mv: raw_value_mv, + }); } let r2 = raw_value_mv * 50.0 / (3.3 - raw_value_mv); @@ -161,12 +163,14 @@ pub async fn determine_tank_state( if board.board_hal.get_config().tank.tank_sensor_enabled { match board .board_hal - .get_tank_sensor().tank_sensor_voltage().await + .get_tank_sensor() + .tank_sensor_voltage() + .await { - Ok(raw_sensor_value_mv) => { - TankState::Present(raw_sensor_value_mv) - }, - Err(err) => TankState::Error(TankError::BoardError { message: err.to_string() }), + Ok(raw_sensor_value_mv) => TankState::Present(raw_sensor_value_mv), + Err(err) => TankState::Error(TankError::BoardError { + message: err.to_string(), + }), } } else { TankState::Disabled diff --git a/Software/MainBoard/rust/src/webserver/get_json.rs b/Software/MainBoard/rust/src/webserver/get_json.rs index 4e57586..5696eba 100644 --- a/Software/MainBoard/rust/src/webserver/get_json.rs +++ b/Software/MainBoard/rust/src/webserver/get_json.rs @@ -93,7 +93,11 @@ where { let mut board = BOARD_ACCESS.get().await.lock().await; let tank_state = determine_tank_state(&mut board).await; - let water_temp: FatResult = board.board_hal.get_tank_sensor().water_temperature_c().await; + let water_temp: FatResult = board + .board_hal + .get_tank_sensor() + .water_temperature_c() + .await; Ok(Some(serde_json::to_string(&tank_state.as_mqtt_info( &board.board_hal.get_config().tank, &water_temp, diff --git a/Software/MainBoard/rust/src/webserver/mod.rs b/Software/MainBoard/rust/src/webserver/mod.rs index 62b6d8c..dcfcb43 100644 --- a/Software/MainBoard/rust/src/webserver/mod.rs +++ b/Software/MainBoard/rust/src/webserver/mod.rs @@ -10,9 +10,9 @@ mod post_json; use crate::fat_error::{FatError, FatResult}; use crate::webserver::backup_manager::{backup_config, backup_info, get_backup_config}; use crate::webserver::get_json::{ - delete_save, get_battery_state, get_config, get_live_moisture, get_log_localization_config, - get_firmware_info_web, get_solar_state, get_time, get_timezones, list_saves, tank_info, - get_wifi_details, + delete_save, get_battery_state, get_config, get_firmware_info_web, get_live_moisture, + get_log_localization_config, get_solar_state, get_time, get_timezones, get_wifi_details, + list_saves, tank_info, }; use crate::webserver::get_log::{get_live_log, get_log}; use crate::webserver::get_static::{serve_bundle, serve_favicon, serve_index};