canbus sensor stub and pcnt impl
This commit is contained in:
		| @@ -160,6 +160,8 @@ option-lock = { version = "0.3.1", default-features = false } | ||||
| #stay in sync with mcutie version here! | ||||
| heapless = { version = "0.7.17", features = ["serde"] } | ||||
| mcutie = { version = "0.3.0", default-features = false, features = ["log", "homeassistant"] } | ||||
| nb = "1.1.0" | ||||
| embedded-can = "0.4.1" | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -168,4 +170,4 @@ mcutie = { git = 'https://github.com/empirephoenix/mcutie.git' } | ||||
| #bq34z100 = { path = "../../bq34z100_rust" } | ||||
|  | ||||
| [build-dependencies] | ||||
| vergen = { version = "8.2.6", features = ["build", "git", "gitcl"] } | ||||
| vergen = { version = "8.2.6", features = ["build", "git", "gitcl"] } | ||||
|   | ||||
| @@ -8,6 +8,7 @@ use embassy_executor::SpawnError; | ||||
| use embassy_sync::mutex::TryLockError; | ||||
| use esp_hal::i2c::master::ConfigError; | ||||
| use esp_hal::pcnt::unit::{InvalidHighLimit, InvalidLowLimit}; | ||||
| use esp_hal::twai::EspTwaiError; | ||||
| use esp_wifi::wifi::WifiError; | ||||
| use ina219::errors::{BusVoltageReadError, ShuntVoltageReadError}; | ||||
| use littlefs2_core::PathError; | ||||
| @@ -60,6 +61,9 @@ pub enum FatError { | ||||
|     ExpanderError { | ||||
|         error: String, | ||||
|     }, | ||||
|     CanBusError { | ||||
|         error: EspTwaiError, | ||||
|     }, | ||||
| } | ||||
|  | ||||
| pub type FatResult<T> = Result<T, FatError>; | ||||
| @@ -88,6 +92,9 @@ impl fmt::Display for FatError { | ||||
|             FatError::DS323 { error } => write!(f, "DS323 {:?}", error), | ||||
|             FatError::Eeprom24x { error } => write!(f, "Eeprom24x {:?}", error), | ||||
|             FatError::ExpanderError { error } => write!(f, "ExpanderError {:?}", error), | ||||
|             FatError::CanBusError { error } => { | ||||
|                 write!(f, "CanBusError {:?}", error) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -279,3 +286,14 @@ impl From<InvalidHighLimit> for FatError { | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<nb::Error<EspTwaiError>> for FatError { | ||||
|     fn from(value: nb::Error<EspTwaiError>) -> Self { | ||||
|         match value { | ||||
|             nb::Error::Other(can_error) => FatError::CanBusError { error: can_error }, | ||||
|             nb::Error::WouldBlock => FatError::String { | ||||
|                 error: "Would block".to_string(), | ||||
|             }, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										20
									
								
								rust/src/hal/can_api.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								rust/src/hal/can_api.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| use bincode::{Decode, Encode}; | ||||
|  | ||||
| pub(crate) const SENSOR_BASE_ADDRESS: u16 = 1000; | ||||
| #[derive(Debug, Clone, Copy, Encode, Decode)] | ||||
| pub(crate) struct RequestMoisture { | ||||
|     pub(crate) sensor: Sensor, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Clone, Copy, Encode, Decode)] | ||||
| pub(crate) struct ResponseMoisture { | ||||
|     pub plant: u8, | ||||
|     pub sensor: Sensor, | ||||
|     pub hz: u32, | ||||
| } | ||||
|  | ||||
| #[derive(Debug, Clone, Copy, Encode, Decode, PartialEq, Eq)] | ||||
| pub(crate) enum Sensor { | ||||
|     A, | ||||
|     B, | ||||
| } | ||||
| @@ -892,8 +892,8 @@ async fn mqtt_incoming_task( | ||||
|                 MQTT_CONNECTED_EVENT_RECEIVED.store(true, Ordering::Relaxed); | ||||
|             } | ||||
|             MqttMessage::Publish(topic, payload) => match topic { | ||||
|                 Topic::DeviceType(type_topic) => {} | ||||
|                 Topic::Device(device_topic) => {} | ||||
|                 Topic::DeviceType(_type_topic) => {} | ||||
|                 Topic::Device(_device_topic) => {} | ||||
|                 Topic::General(topic) => { | ||||
|                     let subtopic = topic.as_str(); | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| pub(crate) mod battery; | ||||
| mod can_api; | ||||
| pub mod esp; | ||||
| mod initial_hal; | ||||
| mod little_fs2storage_adapter; | ||||
| @@ -13,7 +14,6 @@ use crate::alloc::string::ToString; | ||||
| use crate::hal::rtc::{DS3231Module, RTCModuleInteraction}; | ||||
| use esp_hal::peripherals::Peripherals; | ||||
| use esp_hal::peripherals::ADC1; | ||||
| use esp_hal::peripherals::APB_SARADC; | ||||
| use esp_hal::peripherals::GPIO0; | ||||
| use esp_hal::peripherals::GPIO10; | ||||
| use esp_hal::peripherals::GPIO11; | ||||
| @@ -41,7 +41,6 @@ use esp_hal::peripherals::GPIO5; | ||||
| use esp_hal::peripherals::GPIO6; | ||||
| use esp_hal::peripherals::GPIO7; | ||||
| use esp_hal::peripherals::GPIO8; | ||||
| use esp_hal::peripherals::PCNT; | ||||
| use esp_hal::peripherals::TWAI0; | ||||
|  | ||||
| use crate::{ | ||||
|   | ||||
| @@ -20,7 +20,6 @@ use embassy_time::Timer; | ||||
| use embedded_hal::digital::OutputPin as _; | ||||
| use esp_hal::gpio::{Flex, Input, InputConfig, Level, Output, OutputConfig, Pull}; | ||||
| use esp_hal::pcnt::channel::CtrlMode::Keep; | ||||
| use esp_hal::pcnt::channel::EdgeMode; | ||||
| use esp_hal::pcnt::channel::EdgeMode::{Hold, Increment}; | ||||
| use esp_hal::pcnt::unit::Unit; | ||||
| use measurements::{Current, Voltage}; | ||||
| @@ -146,7 +145,6 @@ pub(crate) fn create_v3( | ||||
|  | ||||
|     let signal_counter = peripherals.pcnt0; | ||||
|  | ||||
|     signal_counter.set_low_limit(Some(0))?; | ||||
|     signal_counter.set_high_limit(Some(i16::MAX))?; | ||||
|  | ||||
|     let ch0 = &signal_counter.channel0; | ||||
|   | ||||
| @@ -1,28 +1,25 @@ | ||||
| use crate::bail; | ||||
| use crate::config::PlantControllerConfig; | ||||
| use crate::fat_error::{FatError, FatResult}; | ||||
| use crate::hal::battery::BatteryInteraction; | ||||
| use crate::hal::esp::{hold_disable, hold_enable, Esp}; | ||||
| use crate::hal::rtc::RTCModuleInteraction; | ||||
| use crate::hal::v4_sensor::{SensorImpl, SensorInteraction}; | ||||
| use crate::hal::water::TankSensor; | ||||
| use crate::hal::{BoardInteraction, FreePeripherals, Sensor, I2C_DRIVER, PLANT_COUNT, TIME_ACCESS}; | ||||
| use crate::log::{LogMessage, LOG_ACCESS}; | ||||
| use alloc::boxed::Box; | ||||
| use alloc::string::ToString; | ||||
| use async_trait::async_trait; | ||||
| use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; | ||||
| use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||||
| use embassy_time::Timer; | ||||
| use esp_hal::{twai, Blocking}; | ||||
| //use embedded_hal_bus::i2c::MutexDevice; | ||||
| use crate::bail; | ||||
| use crate::fat_error::{FatError, FatResult}; | ||||
| use crate::hal::v4_sensor::{SensorImpl, SensorInteraction}; | ||||
| use crate::log::{LogMessage, LOG_ACCESS}; | ||||
| use esp_hal::gpio::{Flex, Input, InputConfig, Level, Output, OutputConfig, Pull}; | ||||
| use esp_hal::i2c::master::I2c; | ||||
| use esp_hal::pcnt::channel::CtrlMode::Keep; | ||||
| use esp_hal::pcnt::channel::EdgeMode::{Hold, Increment}; | ||||
| use esp_hal::pcnt::Pcnt; | ||||
| use esp_hal::twai::{EspTwaiFrame, StandardId, TwaiMode}; | ||||
| use esp_println::println; | ||||
| use esp_hal::twai::TwaiMode; | ||||
| use esp_hal::{twai, Blocking}; | ||||
| use ina219::address::{Address, Pin}; | ||||
| use ina219::calibration::UnCalibrated; | ||||
| use ina219::configuration::{Configuration, OperatingMode, Resolution}; | ||||
| @@ -179,7 +176,6 @@ pub(crate) async fn create_v4( | ||||
|  | ||||
|             let signal_counter = peripherals.pcnt0; | ||||
|  | ||||
|             signal_counter.set_low_limit(Some(0))?; | ||||
|             signal_counter.set_high_limit(Some(i16::MAX))?; | ||||
|  | ||||
|             let ch0 = &signal_counter.channel0; | ||||
| @@ -203,23 +199,20 @@ pub(crate) async fn create_v4( | ||||
|         } | ||||
|         Err(_) => { | ||||
|             log::info!("Can bus mode "); | ||||
|             let twai_config = twai::TwaiConfiguration::new( | ||||
|             let twai_config = Some(twai::TwaiConfiguration::new( | ||||
|                 peripherals.twai, | ||||
|                 peripherals.gpio0, | ||||
|                 peripherals.gpio2, | ||||
|                 TWAI_BAUDRATE, | ||||
|                 TwaiMode::Normal, | ||||
|             ); | ||||
|             )); | ||||
|             let can_power = Output::new(peripherals.gpio22, Level::Low, OutputConfig::default()); | ||||
|  | ||||
|             let mut twai = twai_config.start(); | ||||
|             let frame = EspTwaiFrame::new(StandardId::ZERO, &[1, 2, 3]).unwrap(); | ||||
|  | ||||
|             twai.transmit(&frame).unwrap(); | ||||
|  | ||||
|             //            let frame = twai.receive().unwrap(); | ||||
|             println!("Received a frame: {frame:?}"); | ||||
|             //can bus version | ||||
|             SensorImpl::CanBus { twai } | ||||
|             SensorImpl::CanBus { | ||||
|                 twai_config, | ||||
|                 can_power, | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| @@ -409,6 +402,14 @@ impl<'a> BoardInteraction<'a> for V4<'a> { | ||||
|         Timer::after_millis(100).await; | ||||
|         self.general_fault(false).await; | ||||
|         Timer::after_millis(500).await; | ||||
|         self.extra1.set_high(); | ||||
|         Timer::after_millis(500).await; | ||||
|         self.extra1.set_low(); | ||||
|         Timer::after_millis(500).await; | ||||
|         self.extra2.set_high(); | ||||
|         Timer::after_millis(500).await; | ||||
|         self.extra2.set_low(); | ||||
|         Timer::after_millis(500).await; | ||||
|         self.light(true).await?; | ||||
|         Timer::after_millis(500).await; | ||||
|         self.light(false).await?; | ||||
|   | ||||
| @@ -1,17 +1,25 @@ | ||||
| use crate::fat_error::{FatError, FatResult}; | ||||
| use crate::hal::Box; | ||||
| use crate::bail; | ||||
| use crate::fat_error::{ContextExt, FatError, FatResult}; | ||||
| use crate::hal::can_api::ResponseMoisture; | ||||
| use crate::hal::Sensor; | ||||
| use crate::hal::{can_api, Box}; | ||||
| use crate::log::{LogMessage, LOG_ACCESS}; | ||||
| use alloc::format; | ||||
| use alloc::string::ToString; | ||||
| use async_trait::async_trait; | ||||
| use bincode::config; | ||||
| use bincode::error::DecodeError; | ||||
| use can_api::RequestMoisture; | ||||
| use embassy_embedded_hal::shared_bus::blocking::i2c::I2cDevice; | ||||
| use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | ||||
| use embassy_time::Timer; | ||||
| use embassy_time::{Instant, Timer}; | ||||
| use embedded_can::Frame; | ||||
| use esp_hal::gpio::Output; | ||||
| use esp_hal::i2c::master::I2c; | ||||
| use esp_hal::pcnt::unit::Unit; | ||||
| use esp_hal::twai::Twai; | ||||
| use esp_hal::twai::{EspTwaiFrame, StandardId, Twai, TwaiConfiguration}; | ||||
| use esp_hal::Blocking; | ||||
| use log::info; | ||||
| use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface}; | ||||
|  | ||||
| const REPEAT_MOIST_MEASURE: usize = 10; | ||||
| @@ -35,7 +43,8 @@ pub enum SensorImpl { | ||||
|             Pca9535Immediate<I2cDevice<'static, CriticalSectionRawMutex, I2c<'static, Blocking>>>, | ||||
|     }, | ||||
|     CanBus { | ||||
|         twai: Twai<'static, Blocking>, | ||||
|         twai_config: Option<TwaiConfiguration<'static, Blocking>>, | ||||
|         can_power: Output<'static>, | ||||
|     }, | ||||
| } | ||||
|  | ||||
| @@ -122,9 +131,95 @@ impl SensorInteraction for SensorImpl { | ||||
|                 let median = results[mid]; | ||||
|                 Ok(median) | ||||
|             } | ||||
|             SensorImpl::CanBus { twai } => Err(FatError::String { | ||||
|                 error: "Not yet implemented".to_string(), | ||||
|             }), | ||||
|  | ||||
|             SensorImpl::CanBus { | ||||
|                 twai_config, | ||||
|                 can_power, | ||||
|             } => { | ||||
|                 can_power.set_high(); | ||||
|                 let config = twai_config.take().expect("twai config not set"); | ||||
|                 let mut twai = config.start(); | ||||
|  | ||||
|                 Timer::after_millis(10).await; | ||||
|                 let can = Self::inner_can(plant, sensor, &mut twai).await; | ||||
|                 can_power.set_low(); | ||||
|                 let config = twai.stop(); | ||||
|                 twai_config.replace(config); | ||||
|  | ||||
|                 let value = can?; | ||||
|                 Ok(value) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl SensorImpl { | ||||
|     async fn inner_can( | ||||
|         plant: usize, | ||||
|         sensor: Sensor, | ||||
|         twai: &mut Twai<'static, Blocking>, | ||||
|     ) -> FatResult<f32> { | ||||
|         let can_sensor: can_api::Sensor = sensor.into(); | ||||
|         let request = RequestMoisture { sensor: can_sensor }; | ||||
|         let mut can_buffer = [0_u8; 8]; | ||||
|         let config = config::standard(); | ||||
|         let encoded = bincode::encode_into_slice(&request, &mut can_buffer, config)?; | ||||
|  | ||||
|         let address = StandardId::new(can_api::SENSOR_BASE_ADDRESS + plant as u16) | ||||
|             .context(">> Could not create address for sensor! (plant: {}) <<")?; | ||||
|         let request = EspTwaiFrame::new(address, &can_buffer[0..encoded]) | ||||
|             .context("Error building CAN frame")?; | ||||
|         twai.transmit(&request)?; | ||||
|  | ||||
|         let timeout = Instant::now() | ||||
|             .checked_add(embassy_time::Duration::from_millis(100)) | ||||
|             .context("Timeout")?; | ||||
|         loop { | ||||
|             let answer = twai.receive(); | ||||
|             match answer { | ||||
|                 Ok(answer) => { | ||||
|                     let data = EspTwaiFrame::data(&answer); | ||||
|                     let response: Result<(ResponseMoisture, usize), DecodeError> = | ||||
|                         bincode::decode_from_slice(&data, config); | ||||
|                     info!("Can answer {response:?}"); | ||||
|                     let value = response?.0; | ||||
|                     if (value.plant as usize) != plant { | ||||
|                         bail!( | ||||
|                             "Received answer for wrong plant! Expected: {}, got: {}", | ||||
|                             plant, | ||||
|                             value.plant | ||||
|                         ); | ||||
|                     } | ||||
|                     if value.sensor != can_sensor { | ||||
|                         bail!( | ||||
|                             "Received answer for wrong sensor! Expected: {:?}, got: {:?}", | ||||
|                             can_sensor, | ||||
|                             value.sensor | ||||
|                         ); | ||||
|                     } | ||||
|                     return Ok(value.hz as f32); | ||||
|                 } | ||||
|                 Err(error) => match error { | ||||
|                     nb::Error::Other(error) => { | ||||
|                         return Err(FatError::CanBusError { error }); | ||||
|                     } | ||||
|                     nb::Error::WouldBlock => { | ||||
|                         if Instant::now() > timeout { | ||||
|                             bail!("Timeout waiting for CAN answer"); | ||||
|                         } | ||||
|                         Timer::after_millis(10).await; | ||||
|                     } | ||||
|                 }, | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| impl From<Sensor> for can_api::Sensor { | ||||
|     fn from(value: Sensor) -> Self { | ||||
|         match value { | ||||
|             Sensor::A => can_api::Sensor::A, | ||||
|             Sensor::B => can_api::Sensor::B, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -5,6 +5,8 @@ use embassy_time::Timer; | ||||
| use esp_hal::analog::adc::{Adc, AdcConfig, AdcPin, Attenuation}; | ||||
| use esp_hal::delay::Delay; | ||||
| use esp_hal::gpio::{Flex, Input, 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::peripherals::GPIO5; | ||||
| use esp_hal::Blocking; | ||||
| @@ -16,8 +18,7 @@ pub struct TankSensor<'a> { | ||||
|     tank_channel: Adc<'a, ADC1<'a>, Blocking>, | ||||
|     tank_power: Output<'a>, | ||||
|     tank_pin: AdcPin<GPIO5<'a>, ADC1<'a>>, | ||||
|     // flow_counter: PcntDriver<'a>, | ||||
|     // delay: Delay, | ||||
|     flow_counter: Unit<'a, 1>, | ||||
| } | ||||
|  | ||||
| impl<'a> TankSensor<'a> { | ||||
| @@ -37,54 +38,38 @@ impl<'a> TankSensor<'a> { | ||||
|  | ||||
|         let one_wire_bus = OneWire::new(one_wire_pin, false); | ||||
|  | ||||
|         // | ||||
|         // let mut flow_counter = PcntDriver::new( | ||||
|         //     pcnt1, | ||||
|         //     Some(flow_sensor_pin), | ||||
|         //     Option::<AnyInputPin>::None, | ||||
|         //     Option::<AnyInputPin>::None, | ||||
|         //     Option::<AnyInputPin>::None, | ||||
|         // )?; | ||||
|         // | ||||
|         // flow_counter.channel_config( | ||||
|         //     PcntChannel::Channel1, | ||||
|         //     PinIndex::Pin0, | ||||
|         //     PinIndex::Pin1, | ||||
|         //     &PcntChannelConfig { | ||||
|         //         lctrl_mode: PcntControlMode::Keep, | ||||
|         //         hctrl_mode: PcntControlMode::Keep, | ||||
|         //         pos_mode: PcntCountMode::Increment, | ||||
|         //         neg_mode: PcntCountMode::Hold, | ||||
|         //         counter_h_lim: i16::MAX, | ||||
|         //         counter_l_lim: 0, | ||||
|         //     }, | ||||
|         // )?; | ||||
|         // | ||||
|         pcnt1.set_high_limit(Some(i16::MAX))?; | ||||
|  | ||||
|         let ch0 = &pcnt1.channel0; | ||||
|         ch0.set_edge_signal(flow_sensor.peripheral_input()); | ||||
|         ch0.set_input_mode(Hold, Increment); | ||||
|         ch0.set_ctrl_mode(Keep, Keep); | ||||
|         pcnt1.listen(); | ||||
|  | ||||
|         Ok(TankSensor { | ||||
|             one_wire_bus, | ||||
|             tank_channel, | ||||
|             tank_power, | ||||
|             tank_pin, //     flow_counter, | ||||
|                       //     delay: Default::default(), | ||||
|             tank_pin, | ||||
|             flow_counter: pcnt1, | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub fn reset_flow_meter(&mut self) { | ||||
|         // self.flow_counter.counter_pause().unwrap(); | ||||
|         // self.flow_counter.counter_clear().unwrap(); | ||||
|         self.flow_counter.pause(); | ||||
|         self.flow_counter.clear(); | ||||
|     } | ||||
|  | ||||
|     pub fn start_flow_meter(&mut self) { | ||||
|         //self.flow_counter.counter_resume().unwrap(); | ||||
|         self.flow_counter.resume(); | ||||
|     } | ||||
|  | ||||
|     pub fn get_flow_meter_value(&mut self) -> i16 { | ||||
|         //self.flow_counter.get_counter_value().unwrap() | ||||
|         5_i16 | ||||
|         self.flow_counter.value() | ||||
|     } | ||||
|  | ||||
|     pub fn stop_flow_meter(&mut self) -> i16 { | ||||
|         //self.flow_counter.counter_pause().unwrap(); | ||||
|         self.flow_counter.pause(); | ||||
|         self.get_flow_meter_value() | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -77,6 +77,20 @@ impl From<LogEntryInner> for LogEntry { | ||||
|     } | ||||
| } | ||||
|  | ||||
| pub async fn log( | ||||
|     message_key: LogMessage, | ||||
|     number_a: u32, | ||||
|     number_b: u32, | ||||
|     txt_short: &str, | ||||
|     txt_long: &str, | ||||
| ) { | ||||
|     LOG_ACCESS | ||||
|         .lock() | ||||
|         .await | ||||
|         .log(message_key, number_a, number_b, txt_short, txt_long) | ||||
|         .await | ||||
| } | ||||
|  | ||||
| impl LogArray { | ||||
|     pub fn get(&mut self) -> Vec<LogEntry> { | ||||
|         let head: RangedU8<0, MAX_LOG_ARRAY_INDEX> = | ||||
|   | ||||
							
								
								
									
										216
									
								
								rust/src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										216
									
								
								rust/src/main.rs
									
									
									
									
									
								
							| @@ -17,7 +17,7 @@ use crate::config::{NetworkConfig, PlantConfig}; | ||||
| use crate::fat_error::FatResult; | ||||
| use crate::hal::esp::MQTT_STAY_ALIVE; | ||||
| use crate::hal::{esp_time, TIME_ACCESS}; | ||||
| use crate::log::LOG_ACCESS; | ||||
| use crate::log::{log, LOG_ACCESS}; | ||||
| use crate::tank::{determine_tank_state, TankError, TankState, WATER_FROZEN_THRESH}; | ||||
| use crate::webserver::http_server; | ||||
| use crate::{ | ||||
| @@ -326,7 +326,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { | ||||
|             .await; | ||||
|     } | ||||
|  | ||||
|     let _dry_run = false; | ||||
|     let dry_run = false; | ||||
|  | ||||
|     let tank_state = determine_tank_state(&mut board).await; | ||||
|  | ||||
| @@ -383,7 +383,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     let mut _water_frozen = false; | ||||
|     let mut water_frozen = false; | ||||
|     let water_temp: FatResult<f32> = match board.board_hal.get_tank_sensor() { | ||||
|         Ok(sensor) => sensor.water_temperature_c().await, | ||||
|         Err(e) => Err(e), | ||||
| @@ -391,7 +391,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { | ||||
|  | ||||
|     if let Ok(res) = water_temp { | ||||
|         if res < WATER_FROZEN_THRESH { | ||||
|             _water_frozen = true; | ||||
|             water_frozen = true; | ||||
|         } | ||||
|     } | ||||
|     info!("Water temp is {}", water_temp.as_ref().unwrap_or(&0.)); | ||||
| @@ -411,74 +411,81 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> { | ||||
|  | ||||
|     publish_plant_states(&mut board, &timezone_time.clone(), &plantstate).await; | ||||
|  | ||||
|     // let pump_required = plantstate | ||||
|     //     .iter() | ||||
|     //     .zip(&board.board_hal.get_config().plants) | ||||
|     //     .any(|(it, conf)| it.needs_to_be_watered(conf, &timezone_time)) | ||||
|     //     && !water_frozen; | ||||
|     // if pump_required { | ||||
|     //     log(LogMessage::EnableMain, dry_run as u32, 0, "", ""); | ||||
|     //     for (plant_id, (state, plant_config)) in plantstate | ||||
|     //         .iter() | ||||
|     //         .zip(&board.board_hal.get_config().plants.clone()) | ||||
|     //         .enumerate() | ||||
|     //     { | ||||
|     //         if state.needs_to_be_watered(plant_config, &timezone_time) { | ||||
|     //             let pump_count = board.board_hal.get_esp().consecutive_pump_count(plant_id) + 1; | ||||
|     //             board | ||||
|     //                 .board_hal | ||||
|     //                 .get_esp() | ||||
|     //                 .store_consecutive_pump_count(plant_id, pump_count); | ||||
|     // | ||||
|     //             let pump_ineffective = pump_count > plant_config.max_consecutive_pump_count as u32; | ||||
|     //             if pump_ineffective { | ||||
|     //                 log( | ||||
|     //                     LogMessage::ConsecutivePumpCountLimit, | ||||
|     //                     pump_count, | ||||
|     //                     plant_config.max_consecutive_pump_count as u32, | ||||
|     //                     &(plant_id + 1).to_string(), | ||||
|     //                     "", | ||||
|     //                 ); | ||||
|     //                 board.board_hal.fault(plant_id, true).await?; | ||||
|     //             } | ||||
|     //             log( | ||||
|     //                 LogMessage::PumpPlant, | ||||
|     //                 (plant_id + 1) as u32, | ||||
|     //                 plant_config.pump_time_s as u32, | ||||
|     //                 &dry_run.to_string(), | ||||
|     //                 "", | ||||
|     //             ); | ||||
|     //             board | ||||
|     //                 .board_hal | ||||
|     //                 .get_esp() | ||||
|     //                 .store_last_pump_time(plant_id, cur); | ||||
|     //             board.board_hal.get_esp().last_pump_time(plant_id); | ||||
|     //             //state.active = true; | ||||
|     // | ||||
|     //             pump_info(plant_id, true, pump_ineffective, 0, 0, 0, false).await; | ||||
|     // | ||||
|     //             let result = do_secure_pump(plant_id, plant_config, dry_run).await?; | ||||
|     //             board.board_hal.pump(plant_id, false).await?; | ||||
|     //             pump_info( | ||||
|     //                 plant_id, | ||||
|     //                 false, | ||||
|     //                 pump_ineffective, | ||||
|     //                 result.median_current_ma, | ||||
|     //                 result.max_current_ma, | ||||
|     //                 result.min_current_ma, | ||||
|     //                 result.error, | ||||
|     //             ) | ||||
|     //             .await; | ||||
|     //         } else if !state.pump_in_timeout(plant_config, &timezone_time) { | ||||
|     //             // plant does not need to be watered and is not in timeout | ||||
|     //             // -> reset consecutive pump count | ||||
|     //             board | ||||
|     //                 .board_hal | ||||
|     //                 .get_esp() | ||||
|     //                 .store_consecutive_pump_count(plant_id, 0); | ||||
|     //         } | ||||
|     //     } | ||||
|     // } | ||||
|     let pump_required = plantstate | ||||
|         .iter() | ||||
|         .zip(&board.board_hal.get_config().plants) | ||||
|         .any(|(it, conf)| it.needs_to_be_watered(conf, &timezone_time)) | ||||
|         && !water_frozen; | ||||
|     if pump_required { | ||||
|         LOG_ACCESS | ||||
|             .lock() | ||||
|             .await | ||||
|             .log(LogMessage::EnableMain, dry_run as u32, 0, "", "") | ||||
|             .await; | ||||
|         for (plant_id, (state, plant_config)) in plantstate | ||||
|             .iter() | ||||
|             .zip(&board.board_hal.get_config().plants.clone()) | ||||
|             .enumerate() | ||||
|         { | ||||
|             if state.needs_to_be_watered(plant_config, &timezone_time) { | ||||
|                 let pump_count = board.board_hal.get_esp().consecutive_pump_count(plant_id) + 1; | ||||
|                 board | ||||
|                     .board_hal | ||||
|                     .get_esp() | ||||
|                     .store_consecutive_pump_count(plant_id, pump_count); | ||||
|  | ||||
|                 let pump_ineffective = pump_count > plant_config.max_consecutive_pump_count as u32; | ||||
|                 if pump_ineffective { | ||||
|                     log( | ||||
|                         LogMessage::ConsecutivePumpCountLimit, | ||||
|                         pump_count, | ||||
|                         plant_config.max_consecutive_pump_count as u32, | ||||
|                         &(plant_id + 1).to_string(), | ||||
|                         "", | ||||
|                     ) | ||||
|                     .await; | ||||
|                     board.board_hal.fault(plant_id, true).await?; | ||||
|                 } | ||||
|                 log( | ||||
|                     LogMessage::PumpPlant, | ||||
|                     (plant_id + 1) as u32, | ||||
|                     plant_config.pump_time_s as u32, | ||||
|                     &dry_run.to_string(), | ||||
|                     "", | ||||
|                 ) | ||||
|                 .await; | ||||
|                 board | ||||
|                     .board_hal | ||||
|                     .get_esp() | ||||
|                     .store_last_pump_time(plant_id, cur); | ||||
|                 board.board_hal.get_esp().last_pump_time(plant_id); | ||||
|                 //state.active = true; | ||||
|  | ||||
|                 pump_info(plant_id, true, pump_ineffective, 0, 0, 0, false).await; | ||||
|  | ||||
|                 let result = do_secure_pump(&mut board, plant_id, plant_config, dry_run).await?; | ||||
|                 //stop pump regardless of prior result//todo refactor to inner? | ||||
|                 board.board_hal.pump(plant_id, false).await?; | ||||
|                 pump_info( | ||||
|                     plant_id, | ||||
|                     false, | ||||
|                     pump_ineffective, | ||||
|                     result.median_current_ma, | ||||
|                     result.max_current_ma, | ||||
|                     result.min_current_ma, | ||||
|                     result.error, | ||||
|                 ) | ||||
|                 .await; | ||||
|             } else if !state.pump_in_timeout(plant_config, &timezone_time) { | ||||
|                 // plant does not need to be watered and is not in timeout | ||||
|                 // -> reset consecutive pump count | ||||
|                 board | ||||
|                     .board_hal | ||||
|                     .get_esp() | ||||
|                     .store_consecutive_pump_count(plant_id, 0); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     info!("state of charg"); | ||||
|     let is_day = board.board_hal.is_day(); | ||||
| @@ -671,17 +678,14 @@ pub async fn do_secure_pump( | ||||
|                     let high_current = current_ma > plant_config.max_pump_current_ma; | ||||
|                     if high_current { | ||||
|                         if first_error { | ||||
|                             LOG_ACCESS | ||||
|                                 .lock() | ||||
|                                 .await | ||||
|                                 .log( | ||||
|                                     LogMessage::PumpOverCurrent, | ||||
|                                     plant_id as u32 + 1, | ||||
|                                     current_ma as u32, | ||||
|                                     plant_config.max_pump_current_ma.to_string().as_str(), | ||||
|                                     step.to_string().as_str(), | ||||
|                                 ) | ||||
|                                 .await; | ||||
|                             log( | ||||
|                                 LogMessage::PumpOverCurrent, | ||||
|                                 plant_id as u32 + 1, | ||||
|                                 current_ma as u32, | ||||
|                                 plant_config.max_pump_current_ma.to_string().as_str(), | ||||
|                                 step.to_string().as_str(), | ||||
|                             ) | ||||
|                             .await; | ||||
|                             board.board_hal.general_fault(true).await; | ||||
|                             board.board_hal.fault(plant_id, true).await?; | ||||
|                             if !plant_config.ignore_current_error { | ||||
| @@ -694,17 +698,14 @@ pub async fn do_secure_pump( | ||||
|                     let low_current = current_ma < plant_config.min_pump_current_ma; | ||||
|                     if low_current { | ||||
|                         if first_error { | ||||
|                             LOG_ACCESS | ||||
|                                 .lock() | ||||
|                                 .await | ||||
|                                 .log( | ||||
|                                     LogMessage::PumpOpenLoopCurrent, | ||||
|                                     plant_id as u32 + 1, | ||||
|                                     current_ma as u32, | ||||
|                                     plant_config.min_pump_current_ma.to_string().as_str(), | ||||
|                                     step.to_string().as_str(), | ||||
|                                 ) | ||||
|                                 .await; | ||||
|                             log( | ||||
|                                 LogMessage::PumpOpenLoopCurrent, | ||||
|                                 plant_id as u32 + 1, | ||||
|                                 current_ma as u32, | ||||
|                                 plant_config.min_pump_current_ma.to_string().as_str(), | ||||
|                                 step.to_string().as_str(), | ||||
|                             ) | ||||
|                             .await; | ||||
|                             board.board_hal.general_fault(true).await; | ||||
|                             board.board_hal.fault(plant_id, true).await?; | ||||
|                             if !plant_config.ignore_current_error { | ||||
| @@ -718,17 +719,14 @@ pub async fn do_secure_pump( | ||||
|                 Err(err) => { | ||||
|                     if !plant_config.ignore_current_error { | ||||
|                         info!("Error getting pump current: {}", err); | ||||
|                         LOG_ACCESS | ||||
|                             .lock() | ||||
|                             .await | ||||
|                             .log( | ||||
|                                 LogMessage::PumpMissingSensorCurrent, | ||||
|                                 plant_id as u32, | ||||
|                                 0, | ||||
|                                 "", | ||||
|                                 "", | ||||
|                             ) | ||||
|                             .await; | ||||
|                         log( | ||||
|                             LogMessage::PumpMissingSensorCurrent, | ||||
|                             plant_id as u32, | ||||
|                             0, | ||||
|                             "", | ||||
|                             "", | ||||
|                         ) | ||||
|                         .await; | ||||
|                         error = true; | ||||
|                         break; | ||||
|                     } else { | ||||
| @@ -1003,21 +1001,21 @@ async fn wait_infinity( | ||||
|                     led_count %= 8; | ||||
|                     led_count += 1; | ||||
|                     for i in 0..8 { | ||||
|                         let _ = board.board_hal.fault(i, i < led_count); | ||||
|                         let _ = board.board_hal.fault(i, i < led_count).await; | ||||
|                     } | ||||
|                 } | ||||
|                 WaitType::ConfigButton => { | ||||
|                     // Alternating pattern: 1010 1010 -> 0101 0101 | ||||
|                     pattern_step = (pattern_step + 1) % 2; | ||||
|                     for i in 0..8 { | ||||
|                         let _ = board.board_hal.fault(i, (i + pattern_step) % 2 == 0); | ||||
|                         let _ = board.board_hal.fault(i, (i + pattern_step) % 2 == 0).await; | ||||
|                     } | ||||
|                 } | ||||
|                 WaitType::MqttConfig => { | ||||
|                     // Moving dot pattern | ||||
|                     pattern_step = (pattern_step + 1) % 8; | ||||
|                     for i in 0..8 { | ||||
|                         let _ = board.board_hal.fault(i, i == pattern_step); | ||||
|                         let _ = board.board_hal.fault(i, i == pattern_step).await; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @@ -1031,7 +1029,7 @@ async fn wait_infinity( | ||||
|  | ||||
|             // Clear all LEDs | ||||
|             for i in 0..8 { | ||||
|                 let _ = board.board_hal.fault(i, false); | ||||
|                 let _ = board.board_hal.fault(i, false).await; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user