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