use crate::alloc::boxed::Box; use crate::fat_error::{FatError, FatResult}; use crate::hal::esp::Esp; use crate::hal::rtc::{BackupHeader, RTCModuleInteraction}; use crate::hal::water::TankSensor; use crate::hal::{BoardInteraction, FreePeripherals, Moistures, TIME_ACCESS}; use crate::{ bail, config::PlantControllerConfig, hal::battery::{BatteryInteraction, NoBatteryMonitor}, }; use async_trait::async_trait; use chrono::{DateTime, Utc}; use esp_hal::gpio::{Level, Output, OutputConfig}; use measurements::{Current, Voltage}; pub struct Initial<'a> { pub(crate) general_fault: Output<'a>, pub(crate) esp: Esp<'a>, pub(crate) config: PlantControllerConfig, pub(crate) battery: Box, pub rtc: Box, } pub(crate) struct NoRTC {} #[async_trait(?Send)] impl RTCModuleInteraction for NoRTC { async fn get_backup_info(&mut self) -> Result { bail!("Please configure board revision") } async fn get_backup_config(&mut self, _chunk: usize) -> FatResult<([u8; 32], usize, u16)> { bail!("Please configure board revision") } async fn backup_config(&mut self, _offset: usize, _bytes: &[u8]) -> FatResult<()> { bail!("Please configure board revision") } async fn backup_config_finalize(&mut self, _crc: u16, _length: usize) -> FatResult<()> { bail!("Please configure board revision") } async fn get_rtc_time(&mut self) -> Result, FatError> { bail!("Please configure board revision") } async fn set_rtc_time(&mut self, _time: &DateTime) -> Result<(), FatError> { bail!("Please configure board revision") } } pub(crate) fn create_initial_board( free_pins: FreePeripherals<'static>, config: PlantControllerConfig, esp: Esp<'static>, ) -> Result + Send>, FatError> { log::info!("Start initial"); let general_fault = Output::new(free_pins.gpio23, Level::Low, OutputConfig::default()); let v = Initial { general_fault, config, esp, battery: Box::new(NoBatteryMonitor {}), rtc: Box::new(NoRTC {}), }; Ok(Box::new(v)) } #[async_trait(?Send)] impl<'a> BoardInteraction<'a> for Initial<'a> { fn get_tank_sensor(&mut self) -> Result<&mut TankSensor<'a>, FatError> { bail!("Please configure board revision") } fn get_esp(&mut self) -> &mut Esp<'a> { &mut self.esp } fn get_config(&mut self) -> &PlantControllerConfig { &self.config } fn get_battery_monitor(&mut self) -> &mut Box { &mut self.battery } fn get_rtc_module(&mut self) -> &mut Box { &mut self.rtc } async fn set_charge_indicator(&mut self, _charging: bool) -> Result<(), FatError> { bail!("Please configure board revision") } async fn deep_sleep(&mut self, duration_in_ms: u64) -> ! { let rtc = TIME_ACCESS.get().await.lock().await; self.esp.deep_sleep(duration_in_ms, rtc); } fn is_day(&self) -> bool { false } async fn light(&mut self, _enable: bool) -> Result<(), FatError> { bail!("Please configure board revision") } async fn pump(&mut self, _plant: usize, _enable: bool) -> Result<(), FatError> { bail!("Please configure board revision") } async fn pump_current(&mut self, _plant: usize) -> Result { bail!("Please configure board revision") } async fn fault(&mut self, _plant: usize, _enable: bool) -> Result<(), FatError> { bail!("Please configure board revision") } async fn measure_moisture_hz(&mut self) -> Result { bail!("Please configure board revision") } async fn general_fault(&mut self, enable: bool) { self.general_fault.set_level(enable.into()); } async fn test(&mut self) -> Result<(), FatError> { bail!("Please configure board revision") } fn set_config(&mut self, config: PlantControllerConfig) { self.config = config; } async fn get_mptt_voltage(&mut self) -> Result { bail!("Please configure board revision") } async fn get_mptt_current(&mut self) -> Result { bail!("Please configure board revision") } }