add null board

This commit is contained in:
Empire Phoenix 2025-06-11 17:35:23 +02:00
parent 38f4ada433
commit a9d7936376
4 changed files with 118 additions and 40 deletions

View File

@ -184,7 +184,12 @@ fn safe_main() -> anyhow::Result<()> {
} }
println!("cur is {}", cur); println!("cur is {}", cur);
board.update_charge_indicator(); match board.battery_monitor.average_current_milli_ampere() {
Ok(charging) => {
board.set_charge_indicator(charging > 20)
}
Err(_) => {}
}
if board.get_restart_to_conf() { if board.get_restart_to_conf() {
log(LogMessage::ConfigModeSoftwareOverride, 0, 0, "", ""); log(LogMessage::ConfigModeSoftwareOverride, 0, 0, "", "");
@ -362,12 +367,12 @@ fn safe_main() -> anyhow::Result<()> {
if pump_ineffective { if pump_ineffective {
log( log(
LogMessage::ConsecutivePumpCountLimit, LogMessage::ConsecutivePumpCountLimit,
pump_count as u32, pump_count,
plant_config.max_consecutive_pump_count as u32, plant_config.max_consecutive_pump_count as u32,
&(plant_id+1).to_string(), &(plant_id+1).to_string(),
"", "",
); );
board.fault(plant_id, true); board.fault(plant_id, true)?;
} }
log( log(
LogMessage::PumpPlant, LogMessage::PumpPlant,
@ -638,28 +643,30 @@ fn wait_infinity(wait_type: WaitType, reboot_now: Arc<AtomicBool>) -> ! {
loop { loop {
unsafe { unsafe {
let mut lock = BOARD_ACCESS.lock().unwrap(); let mut lock = BOARD_ACCESS.lock().unwrap();
lock.update_charge_indicator(); if let Ok(charging) = lock.battery_monitor.average_current_milli_ampere() {
lock.set_charge_indicator(charging > 20)
}
match wait_type { match wait_type {
WaitType::MissingConfig => { WaitType::MissingConfig => {
// Keep existing behavior: circular filling pattern // Keep existing behavior: circular filling pattern
led_count %= 8; led_count %= 8;
led_count += 1; led_count += 1;
for i in 0..8 { for i in 0..8 {
lock.fault(i, i < led_count); let _ = lock.fault(i, i < led_count);
} }
} }
WaitType::ConfigButton => { WaitType::ConfigButton => {
// Alternating pattern: 1010 1010 -> 0101 0101 // Alternating pattern: 1010 1010 -> 0101 0101
pattern_step = (pattern_step + 1) % 2; pattern_step = (pattern_step + 1) % 2;
for i in 0..8 { for i in 0..8 {
lock.fault(i, (i + pattern_step) % 2 == 0); let _ = lock.fault(i, (i + pattern_step) % 2 == 0);
} }
} }
WaitType::MqttConfig => { WaitType::MqttConfig => {
// Moving dot pattern // Moving dot pattern
pattern_step = (pattern_step + 1) % 8; pattern_step = (pattern_step + 1) % 8;
for i in 0..8 { for i in 0..8 {
lock.fault(i, i == pattern_step); let _ = lock.fault(i, i == pattern_step);
} }
} }
} }
@ -672,7 +679,7 @@ fn wait_infinity(wait_type: WaitType, reboot_now: Arc<AtomicBool>) -> ! {
// Clear all LEDs // Clear all LEDs
for i in 0..8 { for i in 0..8 {
lock.fault(i, false); let _ = lock.fault(i, false);
} }
drop(lock); drop(lock);
vTaskDelay(delay); vTaskDelay(delay);

View File

@ -63,7 +63,7 @@ use one_wire_bus::OneWire;
use crate::config::PlantControllerConfig; use crate::config::PlantControllerConfig;
use crate::log::log; use crate::log::log;
use crate::plant_hal::BoardHal::V3; use crate::plant_hal::BoardHal::V3;
use crate::{to_string, STAY_ALIVE}; use crate::{plant_hal, to_string, STAY_ALIVE};
//Only support for 8 right now! //Only support for 8 right now!
pub const PLANT_COUNT: usize = 8; pub const PLANT_COUNT: usize = 8;
@ -167,6 +167,9 @@ pub struct HAL<'a>{
} }
pub enum BatteryMonitor<'a> { pub enum BatteryMonitor<'a> {
Disabled {
},
BQ34Z100G1 { BQ34Z100G1 {
battery_driver: Bq34z100g1Driver<MutexDevice<'a, I2cDriver<'a>>, Delay> battery_driver: Bq34z100g1Driver<MutexDevice<'a, I2cDriver<'a>>, Delay>
}, },
@ -176,6 +179,9 @@ pub enum BatteryMonitor<'a> {
} }
pub enum BoardHal<'a>{ pub enum BoardHal<'a>{
Initial {
},
V3 { V3 {
shift_register: ShiftRegister40< shift_register: ShiftRegister40<
PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>, PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
@ -269,6 +275,9 @@ impl BatteryInteraction for BatteryMonitor<'_> {
BatteryMonitor::WchI2cSlave { .. } => { BatteryMonitor::WchI2cSlave { .. } => {
bail!("Not implemented") bail!("Not implemented")
} }
BatteryMonitor::Disabled {} => {
bail!("Battery monitor is disabled")
}
} }
} }
@ -282,6 +291,9 @@ impl BatteryInteraction for BatteryMonitor<'_> {
}, },
BatteryMonitor::WchI2cSlave { .. } => { BatteryMonitor::WchI2cSlave { .. } => {
bail!("Not implemented") bail!("Not implemented")
},
&mut BatteryMonitor::Disabled { } => {
bail!("Battery monitor is disabled")
} }
} }
} }
@ -295,6 +307,9 @@ impl BatteryInteraction for BatteryMonitor<'_> {
}, },
BatteryMonitor::WchI2cSlave { .. } => { BatteryMonitor::WchI2cSlave { .. } => {
bail!("Not implemented") bail!("Not implemented")
},
&mut BatteryMonitor::Disabled { } => {
bail!("Battery monitor is disabled")
} }
} }
} }
@ -308,6 +323,9 @@ impl BatteryInteraction for BatteryMonitor<'_> {
}, },
BatteryMonitor::WchI2cSlave { .. } => { BatteryMonitor::WchI2cSlave { .. } => {
bail!("Not implemented") bail!("Not implemented")
},
&mut BatteryMonitor::Disabled { } => {
bail!("Battery monitor is disabled")
} }
} }
} }
@ -321,6 +339,9 @@ impl BatteryInteraction for BatteryMonitor<'_> {
}, },
BatteryMonitor::WchI2cSlave { .. } => { BatteryMonitor::WchI2cSlave { .. } => {
bail!("Not implemented") bail!("Not implemented")
},
&mut BatteryMonitor::Disabled { } => {
bail!("Battery monitor is disabled")
} }
} }
} }
@ -334,6 +355,9 @@ impl BatteryInteraction for BatteryMonitor<'_> {
}, },
BatteryMonitor::WchI2cSlave { .. } => { BatteryMonitor::WchI2cSlave { .. } => {
bail!("Not implemented") bail!("Not implemented")
},
&mut BatteryMonitor::Disabled { } => {
bail!("Battery monitor is disabled")
} }
} }
} }
@ -347,6 +371,9 @@ impl BatteryInteraction for BatteryMonitor<'_> {
}, },
BatteryMonitor::WchI2cSlave { .. } => { BatteryMonitor::WchI2cSlave { .. } => {
bail!("Not implemented") bail!("Not implemented")
},
&mut BatteryMonitor::Disabled { } => {
bail!("Battery monitor is disabled")
} }
} }
} }
@ -360,6 +387,9 @@ impl BatteryInteraction for BatteryMonitor<'_> {
}, },
BatteryMonitor::WchI2cSlave { .. } => { BatteryMonitor::WchI2cSlave { .. } => {
bail!("Not implemented") bail!("Not implemented")
},
&mut BatteryMonitor::Disabled { } => {
bail!("Battery monitor is disabled")
} }
} }
} }
@ -373,30 +403,26 @@ impl BatteryInteraction for BatteryMonitor<'_> {
}, },
BatteryMonitor::WchI2cSlave { .. } => { BatteryMonitor::WchI2cSlave { .. } => {
bail!("Not implemented") bail!("Not implemented")
},
&mut BatteryMonitor::Disabled { } => {
bail!("Battery monitor is disabled")
} }
} }
} }
} }
impl BoardInteraction for HAL<'_> { impl BoardInteraction for HAL<'_> {
fn update_charge_indicator(&mut self) { fn set_charge_indicator(&mut self, charging: bool) {
let is_charging = match &mut self.battery_monitor {
BatteryMonitor::BQ34Z100G1 { battery_driver, .. } => {
match battery_driver.average_current() {
OkStd(current) => current < 20,
Err(_) => false,
}
}
_ => false
};
match &mut self.board_hal { match &mut self.board_hal {
BoardHal::V3 { shift_register, .. } => { BoardHal::V3 { shift_register, .. } => {
shift_register.decompose()[CHARGING] shift_register.decompose()[CHARGING]
.set_state(is_charging.into()) .set_state(charging.into())
.unwrap(); .unwrap();
} }
BoardHal::V4 { .. } => {} BoardHal::V4 { .. } => {},
&mut plant_hal::BoardHal::Initial { } => {
}
} }
} }
fn deep_sleep(&mut self, duration_in_ms: u64) -> ! { fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
@ -404,7 +430,10 @@ impl BoardInteraction for HAL<'_> {
BoardHal::V3 { shift_register, .. } => { BoardHal::V3 { shift_register, .. } => {
shift_register.decompose()[AWAKE].set_low().unwrap(); shift_register.decompose()[AWAKE].set_low().unwrap();
} }
BoardHal::V4 { .. } => {} BoardHal::V4 { .. } => {},
&mut plant_hal::BoardHal::Initial { } => {
}
} }
unsafe { unsafe {
@ -426,7 +455,10 @@ impl BoardInteraction for HAL<'_> {
fn get_backup_info(&mut self) -> Result<BackupHeader> { fn get_backup_info(&mut self) -> Result<BackupHeader> {
let eeprom = match &mut self.board_hal { let eeprom = match &mut self.board_hal {
BoardHal::V3 { eeprom, .. } => {eeprom} BoardHal::V3 { eeprom, .. } => {eeprom}
BoardHal::V4 { eeprom, .. } => {eeprom } BoardHal::V4 { eeprom, .. } => {eeprom },
&mut plant_hal::BoardHal::Initial { } => {
bail!("Board not configured yet")
}
}; };
let dummy = BackupHeader { let dummy = BackupHeader {
timestamp: 0, timestamp: 0,
@ -448,6 +480,9 @@ impl BoardInteraction for HAL<'_> {
let eeprom = match &mut self.board_hal { let eeprom = match &mut self.board_hal {
BoardHal::V3 { eeprom, .. } => {eeprom} BoardHal::V3 { eeprom, .. } => {eeprom}
BoardHal::V4 { eeprom, .. } => {eeprom } BoardHal::V4 { eeprom, .. } => {eeprom }
&mut plant_hal::BoardHal::Initial { } => {
bail!("Board not configured yet")
}
}; };
let dummy = BackupHeader { let dummy = BackupHeader {
@ -489,7 +524,10 @@ impl BoardInteraction for HAL<'_> {
V3 { eeprom, .. } => { V3 { eeprom, .. } => {
eeprom eeprom
} }
BoardHal::V4 { eeprom, .. } => { eeprom } BoardHal::V4 { eeprom, .. } => { eeprom },
&mut plant_hal::BoardHal::Initial { } => {
bail!("Board not configured yet")
}
}; };
let delay = Delay::new_default(); let delay = Delay::new_default();
@ -530,6 +568,9 @@ impl BoardInteraction for HAL<'_> {
eeprom eeprom
} }
BoardHal::V4 { eeprom, .. } => { eeprom } BoardHal::V4 { eeprom, .. } => { eeprom }
&mut plant_hal::BoardHal::Initial { } => {
bail!("Board not configured yet")
}
}; };
match eeprom.write_page(address, chunk) { match eeprom.write_page(address, chunk) {
OkStd(_) => {} OkStd(_) => {}
@ -642,6 +683,9 @@ impl BoardInteraction for HAL<'_> {
match & self.board_hal { match & self.board_hal {
BoardHal::V3 { solar_is_day, .. } => {solar_is_day.get_level().into()} BoardHal::V3 { solar_is_day, .. } => {solar_is_day.get_level().into()}
BoardHal::V4 { solar_is_day, .. } => {solar_is_day.get_level().into() } BoardHal::V4 { solar_is_day, .. } => {solar_is_day.get_level().into() }
plant_hal::BoardHal::Initial {} => {
false
}
} }
} }
//should be multsampled //should be multsampled
@ -679,6 +723,9 @@ impl BoardInteraction for HAL<'_> {
let (tank_power, tank_channel) = match &mut self.board_hal { let (tank_power, tank_channel) = match &mut self.board_hal {
BoardHal::V3 { tank_power, tank_channel, .. } => {(tank_power,tank_channel)} BoardHal::V3 { tank_power, tank_channel, .. } => {(tank_power,tank_channel)}
BoardHal::V4 { tank_power, tank_channel, .. } => {(tank_power,tank_channel) } BoardHal::V4 { tank_power, tank_channel, .. } => {(tank_power,tank_channel) }
&mut plant_hal::BoardHal::Initial { } => {
bail!("Board not configured yet")
}
}; };
@ -711,7 +758,10 @@ impl BoardInteraction for HAL<'_> {
fn light(&mut self, enable: bool) -> Result<()> { fn light(&mut self, enable: bool) -> Result<()> {
let light = match &mut self.board_hal { let light = match &mut self.board_hal {
BoardHal::V3 { light, .. } => light, BoardHal::V3 { light, .. } => light,
BoardHal::V4 { light, .. } => light BoardHal::V4 { light, .. } => light,
&mut plant_hal::BoardHal::Initial { } => {
bail!("Board not configured yet")
}
}; };
unsafe { gpio_hold_dis(light.pin()) }; unsafe { gpio_hold_dis(light.pin()) };
@ -736,7 +786,12 @@ impl BoardInteraction for HAL<'_> {
//currently infallible error, keep for future as result anyway //currently infallible error, keep for future as result anyway
shift_register.decompose()[index].set_state(enable.into())?; shift_register.decompose()[index].set_state(enable.into())?;
} }
BoardHal::V4 { .. } => {} BoardHal::V4 { .. } => {
bail!("Not yet implemented")
},
&plant_hal::BoardHal::Initial {} => {
bail!("Board not configured yet")
}
} }
Ok(()) Ok(())
@ -758,7 +813,7 @@ impl BoardInteraction for HAL<'_> {
fn consecutive_pump_count(&mut self, plant: usize) -> u32 { fn consecutive_pump_count(&mut self, plant: usize) -> u32 {
unsafe { CONSECUTIVE_WATERING_PLANT[plant] } unsafe { CONSECUTIVE_WATERING_PLANT[plant] }
} }
fn fault(& self, plant: usize, enable: bool) { fn fault(& self, plant: usize, enable: bool) -> Result<()>{
match & self.board_hal { match & self.board_hal {
V3 { shift_register, .. } => { V3 { shift_register, .. } => {
let index = match plant { let index = match plant {
@ -773,11 +828,15 @@ impl BoardInteraction for HAL<'_> {
_ => panic!("Invalid plant id {}", plant), _ => panic!("Invalid plant id {}", plant),
}; };
shift_register.decompose()[index] shift_register.decompose()[index]
.set_state(enable.into()) .set_state(enable.into())?;
.unwrap() Ok(())
} }
BoardHal::V4 { .. } => { BoardHal::V4 { .. } => {
bail!("Not yet implemented")
}
&plant_hal::BoardHal::Initial {} => {
bail!("Board not configured yet")
} }
} }
@ -794,6 +853,9 @@ impl BoardInteraction for HAL<'_> {
BoardHal::V4 { main_pump, .. } => { BoardHal::V4 { main_pump, .. } => {
main_pump.set_state(enable.into())?; main_pump.set_state(enable.into())?;
} }
&mut plant_hal::BoardHal::Initial { } => {
bail!("Board not configured yet")
}
} }
Ok(()) Ok(())
@ -922,7 +984,10 @@ impl BoardInteraction for HAL<'_> {
fn general_fault(&mut self, enable: bool) { fn general_fault(&mut self, enable: bool) {
let general_fault = match &mut self.board_hal { let general_fault = match &mut self.board_hal {
BoardHal::V3 { general_fault, .. } => {general_fault} BoardHal::V3 { general_fault, .. } => {general_fault}
BoardHal::V4 { general_fault, .. } => {general_fault} BoardHal::V4 { general_fault, .. } => {general_fault},
&mut plant_hal::BoardHal::Initial { } => {
return
}
}; };
unsafe { gpio_hold_dis(general_fault.pin()) }; unsafe { gpio_hold_dis(general_fault.pin()) };
general_fault.set_state(enable.into()).unwrap(); general_fault.set_state(enable.into()).unwrap();
@ -1056,7 +1121,10 @@ impl BoardInteraction for HAL<'_> {
fn get_rtc_time(&mut self) -> Result<DateTime<Utc>> { fn get_rtc_time(&mut self) -> Result<DateTime<Utc>> {
let rtc = match &mut self.board_hal { let rtc = match &mut self.board_hal {
BoardHal::V3 { rtc, .. } => {rtc} BoardHal::V3 { rtc, .. } => {rtc}
BoardHal::V4 { rtc, .. } => {rtc} BoardHal::V4 { rtc, .. } => {rtc},
&mut plant_hal::BoardHal::Initial { } => {
bail!("Board not configured yet")
}
}; };
match rtc.datetime() { match rtc.datetime() {
OkStd(rtc_time) => Ok(rtc_time.and_utc()), OkStd(rtc_time) => Ok(rtc_time.and_utc()),
@ -1069,6 +1137,9 @@ impl BoardInteraction for HAL<'_> {
let rtc = match &mut self.board_hal { let rtc = match &mut self.board_hal {
BoardHal::V3 { rtc, .. } => {rtc} BoardHal::V3 { rtc, .. } => {rtc}
BoardHal::V4 { rtc, .. } => {rtc} BoardHal::V4 { rtc, .. } => {rtc}
&mut plant_hal::BoardHal::Initial { } => {
bail!("Board not configured yet")
}
}; };
let naive_time = time.naive_utc(); let naive_time = time.naive_utc();
match rtc.set_datetime(&naive_time) { match rtc.set_datetime(&naive_time) {
@ -1122,9 +1193,9 @@ impl BoardInteraction for HAL<'_> {
self.light(false)?; self.light(false)?;
unsafe { vTaskDelay(500) }; unsafe { vTaskDelay(500) };
for i in 0..PLANT_COUNT { for i in 0..PLANT_COUNT {
self.fault(i, true); self.fault(i, true)?;
unsafe { vTaskDelay(500) }; unsafe { vTaskDelay(500) };
self.fault(i, false); self.fault(i, false)?;
unsafe { vTaskDelay(500) }; unsafe { vTaskDelay(500) };
} }
for i in 0..PLANT_COUNT { for i in 0..PLANT_COUNT {
@ -1381,7 +1452,7 @@ pub trait BatteryInteraction {
} }
pub trait BoardInteraction { pub trait BoardInteraction {
fn update_charge_indicator(&mut self); fn set_charge_indicator(&mut self, charging: bool);
fn deep_sleep(&mut self, duration_in_ms: u64) -> !; fn deep_sleep(&mut self, duration_in_ms: u64) -> !;
fn get_backup_info(&mut self) -> Result<BackupHeader>; fn get_backup_info(&mut self) -> Result<BackupHeader>;
fn get_backup_config(&mut self) -> Result<Vec<u8>>; fn get_backup_config(&mut self) -> Result<Vec<u8>>;
@ -1403,7 +1474,7 @@ pub trait BoardInteraction {
fn store_last_pump_time(&mut self, plant: usize, time: DateTime<Utc>); fn store_last_pump_time(&mut self, plant: usize, time: DateTime<Utc>);
fn store_consecutive_pump_count(&mut self, plant: usize, count: u32); fn store_consecutive_pump_count(&mut self, plant: usize, count: u32);
fn consecutive_pump_count(&mut self, plant: usize) -> u32; fn consecutive_pump_count(&mut self, plant: usize) -> u32;
fn fault(&self, plant: usize, enable: bool); fn fault(&self, plant: usize, enable: bool) -> Result<()>;
fn low_voltage_in_cycle(&mut self) -> bool; fn low_voltage_in_cycle(&mut self) -> bool;
fn any_pump(&mut self, enable: bool) -> Result<()>; fn any_pump(&mut self, enable: bool) -> Result<()>;
fn time(&mut self) -> Result<DateTime<Utc>>; fn time(&mut self) -> Result<DateTime<Utc>>;

View File

@ -170,7 +170,7 @@ impl PlantState {
}, },
}; };
if state.is_err() { if state.is_err() {
board.fault(plant_id, true); let _ = board.fault(plant_id, true);
} }
state state
} }

View File

@ -328,7 +328,7 @@ fn ota(
let iter = (total_read / 1024) % 8; let iter = (total_read / 1024) % 8;
if iter != lastiter { if iter != lastiter {
for i in 0..PLANT_COUNT { for i in 0..PLANT_COUNT {
board.fault(i, iter == i); let _ = board.fault(i, iter == i);
} }
lastiter = iter; lastiter = iter;
} }
@ -541,7 +541,7 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
let iter = (total_read / 1024) % 8; let iter = (total_read / 1024) % 8;
if iter != lastiter { if iter != lastiter {
for i in 0..PLANT_COUNT { for i in 0..PLANT_COUNT {
lock.fault(i, iter == i); let _ = lock.fault(i, iter == i);
} }
lastiter = iter; lastiter = iter;
} }