153 lines
4.5 KiB
Rust
153 lines
4.5 KiB
Rust
use crate::config::TankConfig;
|
|
|
|
const OPEN_TANK_VOLTAGE: f32 = 3.0;
|
|
|
|
#[derive(Debug, PartialEq, Default)]
|
|
/// State data for water tank
|
|
///
|
|
/// TODO unify with TankStateMQTT
|
|
pub struct TankInfo {
|
|
/// is there enough water in the tank
|
|
enough_water: bool,
|
|
/// warning that water needs to be refilled soon
|
|
warn_level: bool,
|
|
/// estimation how many ml are still in tank
|
|
left_ml: u32,
|
|
/// if there is was an issue with the water level sensor
|
|
/// TODO merge with left_ml as Result<u32, error_type>
|
|
sensor_error: bool,
|
|
/// raw water sensor value
|
|
raw: u16,
|
|
}
|
|
|
|
pub enum TankError {
|
|
SensorDisabled,
|
|
SensorMissing(f32),
|
|
SensorValueError { value: f32, min: f32, max: f32 },
|
|
}
|
|
|
|
pub enum TankState {
|
|
TankSensorPresent(u16),
|
|
TankSensorDisabled,
|
|
}
|
|
|
|
fn raw_volatge_to_divider_percent(raw_value_mv: u16) -> Result<f32, TankError> {
|
|
if raw_value_mv > OPEN_TANK_VOLTAGE {
|
|
return Err(TankError::SensorMissing(raw_value_mv));
|
|
}
|
|
|
|
let r2 = raw_value_mv * 50.0 / (3.3 - raw_value_mv);
|
|
let mut percent = r2 / 190_f32 * 100_f32;
|
|
percent = percent.clamp(0.0, 100.0);
|
|
// TODO(judge) move this to a sensible place
|
|
//log(
|
|
//LogMessage::SensorTankRaw,
|
|
//raw_value_mv as u32,
|
|
//percent as u32,
|
|
//"",
|
|
//"",
|
|
//);
|
|
Ok(percent)
|
|
}
|
|
|
|
fn raw_voltage_to_tank_fill_percent(
|
|
raw_value_mv: u16,
|
|
config: &TankConfig,
|
|
) -> Result<f32, TankError> {
|
|
let divider_percent = raw_volatge_to_divider_percent(raw_value_mv)?;
|
|
if s < config.tank_empty_percent || s > config.tank_full_percent {
|
|
return Err(TankError::SensorValueError {
|
|
value: divider_percent,
|
|
min: config.tank_empty_percent,
|
|
max: config.tank_full_percent,
|
|
});
|
|
}
|
|
Ok((divider_percent - config.tank_empty_percent) * 100
|
|
/ (config.tank_full_percent - config.tank_empty_percent))
|
|
}
|
|
|
|
|
|
impl TankState {
|
|
pub fn left_ml(&self, config: &TankConfig) -> Result<u32, TankError> {
|
|
match self {
|
|
TankState::TankSensorDisabled => Err(TankError::SensorMissing),
|
|
TankState::TankSensorPresent(raw_value_mv) => {
|
|
let tank_fill_percent = raw_voltage_to_tank_fill_percent(raw_value_mv, config);
|
|
todo!()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
pub struct TankStateMQTT {
|
|
enough_water: bool,
|
|
warn_level: bool,
|
|
left_ml: u32,
|
|
sensor_error: bool,
|
|
raw: u16,
|
|
water_frozen: String,
|
|
}
|
|
|
|
pub fn determine_tank_state(
|
|
board: &mut std::sync::MutexGuard<'_, PlantCtrlBoard<'_>>,
|
|
config: &PlantControllerConfig,
|
|
) -> TankInfo {
|
|
if config.tank.tank_sensor_enabled {
|
|
let mut rv: TankInfo = TankInfo {
|
|
..Default::default()
|
|
};
|
|
let success = board
|
|
.tank_sensor_percent()
|
|
.and_then(|raw| {
|
|
rv.raw = raw;
|
|
return map_range(
|
|
(
|
|
config.tank.tank_empty_percent as f32,
|
|
config.tank.tank_full_percent as f32,
|
|
),
|
|
raw as f32,
|
|
);
|
|
})
|
|
.and_then(|percent| {
|
|
rv.left_ml = ((percent * config.tank.tank_useable_ml as f32) / 100_f32) as u32;
|
|
println!(
|
|
"Tank sensor returned mv {} as {}% leaving {} ml useable",
|
|
rv.raw, percent as u8, rv.left_ml
|
|
);
|
|
if config.tank.tank_warn_percent > percent as u8 {
|
|
board.general_fault(true);
|
|
println!(
|
|
"Low water, current percent is {}, minimum warn level is {}",
|
|
percent as u8, config.tank.tank_warn_percent
|
|
);
|
|
rv.warn_level = true;
|
|
}
|
|
if config.tank.tank_empty_percent < percent as u8 {
|
|
println!(
|
|
"Enough water, current percent is {}, minimum empty level is {}",
|
|
percent as u8, config.tank.tank_empty_percent
|
|
);
|
|
rv.enough_water = true;
|
|
}
|
|
return Ok(());
|
|
});
|
|
match success {
|
|
Err(err) => {
|
|
println!("Could not determine tank value due to {}", err);
|
|
board.general_fault(true);
|
|
rv.sensor_error = true;
|
|
}
|
|
Ok(_) => {}
|
|
}
|
|
return rv;
|
|
}
|
|
return TankInfo {
|
|
warn_level: false,
|
|
enough_water: true,
|
|
left_ml: 1337,
|
|
sensor_error: false,
|
|
raw: 0,
|
|
};
|
|
}
|