allow to selectivly enable redundant sensors
This commit is contained in:
parent
680d1c3aaf
commit
9d1a807805
@ -65,7 +65,7 @@ embedded-svc = { version = "0.27.0", features = ["experimental"] }
|
|||||||
esp-idf-hal = "0.43.0"
|
esp-idf-hal = "0.43.0"
|
||||||
esp-idf-sys = { version = "0.34.0", features = ["binstart", "native"] }
|
esp-idf-sys = { version = "0.34.0", features = ["binstart", "native"] }
|
||||||
esp_idf_build = "0.1.3"
|
esp_idf_build = "0.1.3"
|
||||||
chrono = { version = "0.4.23", default-features = false , features = ["iana-time-zone"] }
|
chrono = { version = "0.4.23", default-features = false , features = ["iana-time-zone" , "alloc"] }
|
||||||
chrono-tz = {version="0.8.0", default-features = false , features = [ "filter-by-regex" ]}
|
chrono-tz = {version="0.8.0", default-features = false , features = [ "filter-by-regex" ]}
|
||||||
embedded-hal = "1.0.0"
|
embedded-hal = "1.0.0"
|
||||||
one-wire-bus = "0.1.1"
|
one-wire-bus = "0.1.1"
|
||||||
|
@ -59,6 +59,8 @@ pub struct Plant {
|
|||||||
pub pump_cooldown_min: u16,
|
pub pump_cooldown_min: u16,
|
||||||
pub pump_hour_start: u8,
|
pub pump_hour_start: u8,
|
||||||
pub pump_hour_end: u8,
|
pub pump_hour_end: u8,
|
||||||
|
pub sensor_b: bool,
|
||||||
|
pub sensor_p: bool
|
||||||
}
|
}
|
||||||
impl Default for Plant {
|
impl Default for Plant {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@ -69,6 +71,8 @@ impl Default for Plant {
|
|||||||
pump_hour_start: 8,
|
pump_hour_start: 8,
|
||||||
pump_hour_end: 20,
|
pump_hour_end: 20,
|
||||||
mode: Mode::OFF,
|
mode: Mode::OFF,
|
||||||
|
sensor_b : false,
|
||||||
|
sensor_p : false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
306
rust/src/main.rs
306
rust/src/main.rs
@ -6,6 +6,7 @@ use std::{
|
|||||||
use chrono::{DateTime, Datelike, Duration, NaiveDateTime, Timelike};
|
use chrono::{DateTime, Datelike, Duration, NaiveDateTime, Timelike};
|
||||||
use chrono_tz::{Europe::Berlin, Tz};
|
use chrono_tz::{Europe::Berlin, Tz};
|
||||||
use config::Plant;
|
use config::Plant;
|
||||||
|
use embedded_svc::mqtt;
|
||||||
use esp_idf_hal::delay::Delay;
|
use esp_idf_hal::delay::Delay;
|
||||||
use esp_idf_sys::{
|
use esp_idf_sys::{
|
||||||
esp_deep_sleep, esp_restart, gpio_deep_sleep_hold_dis, gpio_deep_sleep_hold_en, vTaskDelay,
|
esp_deep_sleep, esp_restart, gpio_deep_sleep_hold_dis, gpio_deep_sleep_hold_en, vTaskDelay,
|
||||||
@ -65,7 +66,7 @@ struct LightState {
|
|||||||
is_day: bool,
|
is_day: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
|
#[derive(Copy, Clone, Debug, PartialEq, Default)]
|
||||||
struct PlantState {
|
struct PlantState {
|
||||||
a: Option<u8>,
|
a: Option<u8>,
|
||||||
b: Option<u8>,
|
b: Option<u8>,
|
||||||
@ -83,6 +84,7 @@ struct PlantState {
|
|||||||
sensor_error_b: Option<SensorError>,
|
sensor_error_b: Option<SensorError>,
|
||||||
sensor_error_p: Option<SensorError>,
|
sensor_error_p: Option<SensorError>,
|
||||||
out_of_work_hour: bool,
|
out_of_work_hour: bool,
|
||||||
|
next_pump: Option<DateTime<Tz>>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
|
||||||
@ -230,7 +232,7 @@ fn safe_main() -> anyhow::Result<()> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
println!("attempting to connect wifi");
|
println!("attempting to connect wifi");
|
||||||
match board.wifi(wifi.ssid, wifi.password, 5000) {
|
match board.wifi(wifi.ssid, wifi.password, 10000) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
online_mode = OnlineMode::Wifi;
|
online_mode = OnlineMode::Wifi;
|
||||||
}
|
}
|
||||||
@ -288,7 +290,10 @@ fn safe_main() -> anyhow::Result<()> {
|
|||||||
if online_mode == OnlineMode::Online {
|
if online_mode == OnlineMode::Online {
|
||||||
let _ = board.mqtt_publish(&config, "/firmware/githash", git_hash.as_bytes());
|
let _ = board.mqtt_publish(&config, "/firmware/githash", git_hash.as_bytes());
|
||||||
let _ = board.mqtt_publish(&config, "/state", "online".as_bytes());
|
let _ = board.mqtt_publish(&config, "/state", "online".as_bytes());
|
||||||
|
let _ = board.mqtt_publish(&config, "/last_online", europe_time.to_rfc3339().as_bytes());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
publish_battery_state(&mut board, &config);
|
publish_battery_state(&mut board, &config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,6 +353,20 @@ fn safe_main() -> anyhow::Result<()> {
|
|||||||
let consecutive_pump_count = board.consecutive_pump_count(plant) + 1;
|
let consecutive_pump_count = board.consecutive_pump_count(plant) + 1;
|
||||||
board.store_consecutive_pump_count(plant, consecutive_pump_count);
|
board.store_consecutive_pump_count(plant, consecutive_pump_count);
|
||||||
let plant_config = config.plants[plant];
|
let plant_config = config.plants[plant];
|
||||||
|
|
||||||
|
|
||||||
|
if plant_config.sensor_p {
|
||||||
|
match map_range_moisture(
|
||||||
|
board.measure_moisture_hz(plant, plant_hal::Sensor::PUMP)? as f32
|
||||||
|
) {
|
||||||
|
Ok(p) => state.p = Some(p),
|
||||||
|
Err(err) => {
|
||||||
|
board.fault(plant, true);
|
||||||
|
state.sensor_error_p = Some(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Trying to pump for {}s with pump {} now",
|
"Trying to pump for {}s with pump {} now",
|
||||||
plant_config.pump_time_s, plant
|
plant_config.pump_time_s, plant
|
||||||
@ -358,32 +377,61 @@ fn safe_main() -> anyhow::Result<()> {
|
|||||||
board.pump(plant, true)?;
|
board.pump(plant, true)?;
|
||||||
board.last_pump_time(plant);
|
board.last_pump_time(plant);
|
||||||
state.active = true;
|
state.active = true;
|
||||||
//FIXME do periodic pump test here and state update
|
for t in 0..plant_config.pump_time_s {
|
||||||
unsafe { vTaskDelay(plant_config.pump_time_s as u32 * CONFIG_FREERTOS_HZ) };
|
//FIXME do periodic pump test here and state update
|
||||||
|
unsafe { vTaskDelay(CONFIG_FREERTOS_HZ) };
|
||||||
|
if plant_config.sensor_p {
|
||||||
|
let moist = map_range_moisture(
|
||||||
|
board.measure_moisture_hz(plant, plant_hal::Sensor::PUMP)? as f32);
|
||||||
|
if online_mode == OnlineMode::Online {
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Sensor P after", plant+1).as_str(),
|
||||||
|
option_to_string(moist.ok()).as_bytes(),
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if online_mode == OnlineMode::Online {
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Sensor P after", plant+1).as_str(),
|
||||||
|
"disabled".as_bytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
board.pump(plant, false)?;
|
board.pump(plant, false)?;
|
||||||
match map_range_moisture(
|
if plant_config.sensor_p {
|
||||||
board.measure_moisture_hz(plant, plant_hal::Sensor::PUMP)? as f32
|
match map_range_moisture(
|
||||||
) {
|
board.measure_moisture_hz(plant, plant_hal::Sensor::PUMP)? as f32
|
||||||
Ok(p) => state.after_p = Some(p),
|
) {
|
||||||
Err(err) => {
|
Ok(p) => state.after_p = Some(p),
|
||||||
|
Err(err) => {
|
||||||
|
board.fault(plant, true);
|
||||||
|
state.sensor_error_p = Some(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if state.after_p.is_none()
|
||||||
|
|| state.p.is_none()
|
||||||
|
|| state.after_p.unwrap() < state.p.unwrap() + 5
|
||||||
|
{
|
||||||
|
state.pump_error = true;
|
||||||
board.fault(plant, true);
|
board.fault(plant, true);
|
||||||
state.sensor_error_p = Some(err);
|
//mqtt sync pump error value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if state.after_p.is_none()
|
|
||||||
|| state.p.is_none()
|
|
||||||
|| state.after_p.unwrap() < state.p.unwrap() + 5
|
|
||||||
{
|
|
||||||
state.pump_error = true;
|
|
||||||
board.fault(plant, true);
|
|
||||||
//mqtt sync pump error value
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
println!("Nothing to do");
|
println!("Nothing to do");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if online_mode == OnlineMode::Online {
|
||||||
|
update_plant_state(&mut plantstate, &mut board, &config);
|
||||||
|
}
|
||||||
let mut light_state = LightState {
|
let mut light_state = LightState {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -700,20 +748,23 @@ fn determine_state_target_moisture_for_plant(
|
|||||||
state.sensor_error_a = Some(SensorError::Unknown);
|
state.sensor_error_a = Some(SensorError::Unknown);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match board.measure_moisture_hz(plant, plant_hal::Sensor::B) {
|
if plant_config.sensor_b {
|
||||||
Ok(b) => {
|
match board.measure_moisture_hz(plant, plant_hal::Sensor::B) {
|
||||||
let mapped = map_range_moisture(b as f32);
|
Ok(b) => {
|
||||||
match mapped {
|
let mapped = map_range_moisture(b as f32);
|
||||||
Ok(result) => state.b = Some(result),
|
match mapped {
|
||||||
Err(err) => {
|
Ok(result) => state.b = Some(result),
|
||||||
state.sensor_error_b = Some(err);
|
Err(err) => {
|
||||||
|
state.sensor_error_b = Some(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Err(_) => {
|
||||||
Err(_) => {
|
state.sensor_error_b = Some(SensorError::Unknown);
|
||||||
state.sensor_error_b = Some(SensorError::Unknown);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//FIXME how to average analyze whatever?
|
//FIXME how to average analyze whatever?
|
||||||
let a_low = state.a.is_some() && state.a.unwrap() < plant_config.target_moisture;
|
let a_low = state.a.is_some() && state.a.unwrap() < plant_config.target_moisture;
|
||||||
let b_low = state.b.is_some() && state.b.unwrap() < plant_config.target_moisture;
|
let b_low = state.b.is_some() && state.b.unwrap() < plant_config.target_moisture;
|
||||||
@ -729,6 +780,8 @@ fn determine_state_target_moisture_for_plant(
|
|||||||
let duration = Duration::minutes((plant_config.pump_cooldown_min).into());
|
let duration = Duration::minutes((plant_config.pump_cooldown_min).into());
|
||||||
let next_pump = board.last_pump_time(plant) + duration;
|
let next_pump = board.last_pump_time(plant) + duration;
|
||||||
if next_pump > cur {
|
if next_pump > cur {
|
||||||
|
let europe_time = next_pump.with_timezone(&Berlin);
|
||||||
|
state.next_pump = Some(europe_time);
|
||||||
state.cooldown = true;
|
state.cooldown = true;
|
||||||
}
|
}
|
||||||
if !in_time_range(
|
if !in_time_range(
|
||||||
@ -779,6 +832,8 @@ fn determine_next_plant(
|
|||||||
let duration = Duration::minutes((plant_config.pump_cooldown_min).into());
|
let duration = Duration::minutes((plant_config.pump_cooldown_min).into());
|
||||||
let next_pump = board.last_pump_time(plant) + duration;
|
let next_pump = board.last_pump_time(plant) + duration;
|
||||||
if next_pump > cur {
|
if next_pump > cur {
|
||||||
|
let europe_time = next_pump.with_timezone(&Berlin);
|
||||||
|
state.next_pump = Some(europe_time);
|
||||||
state.cooldown = true;
|
state.cooldown = true;
|
||||||
} else {
|
} else {
|
||||||
if water_frozen {
|
if water_frozen {
|
||||||
@ -792,6 +847,8 @@ fn determine_next_plant(
|
|||||||
let duration = Duration::minutes((60 * plant_config.pump_cooldown_min).into());
|
let duration = Duration::minutes((60 * plant_config.pump_cooldown_min).into());
|
||||||
let next_pump = board.last_pump_time(plant) + duration;
|
let next_pump = board.last_pump_time(plant) + duration;
|
||||||
if next_pump > cur {
|
if next_pump > cur {
|
||||||
|
let europe_time = next_pump.with_timezone(&Berlin);
|
||||||
|
state.next_pump = Some(europe_time);
|
||||||
state.cooldown = true;
|
state.cooldown = true;
|
||||||
}
|
}
|
||||||
if !in_time_range(
|
if !in_time_range(
|
||||||
@ -828,69 +885,7 @@ fn determine_next_plant(
|
|||||||
println!("Plant {} state is {:?}", plant, state);
|
println!("Plant {} state is {:?}", plant, state);
|
||||||
}
|
}
|
||||||
if online_mode == OnlineMode::Online {
|
if online_mode == OnlineMode::Online {
|
||||||
for plant in 0..PLANT_COUNT {
|
update_plant_state(plantstate, board, config);
|
||||||
let state = &plantstate[plant];
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/Sensor A", plant).as_str(),
|
|
||||||
option_to_string(state.a).as_bytes(),
|
|
||||||
);
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/Sensor B", plant).as_str(),
|
|
||||||
option_to_string(state.b).as_bytes(),
|
|
||||||
);
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/Sensor P before", plant).as_str(),
|
|
||||||
option_to_string(state.p).as_bytes(),
|
|
||||||
);
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/Sensor P after", plant).as_str(),
|
|
||||||
option_to_string(state.after_p).as_bytes(),
|
|
||||||
);
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/Should water", plant).as_str(),
|
|
||||||
state.do_water.to_string().as_bytes(),
|
|
||||||
);
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/Is frozen", plant).as_str(),
|
|
||||||
state.frozen.to_string().as_bytes(),
|
|
||||||
);
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/Is dry", plant).as_str(),
|
|
||||||
state.dry.to_string().as_bytes(),
|
|
||||||
);
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/Pump Error", plant).as_str(),
|
|
||||||
state.pump_error.to_string().as_bytes(),
|
|
||||||
);
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/Pump Ineffective", plant).as_str(),
|
|
||||||
state.not_effective.to_string().as_bytes(),
|
|
||||||
);
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/Is in Cooldown", plant).as_str(),
|
|
||||||
state.cooldown.to_string().as_bytes(),
|
|
||||||
);
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/No Water", plant).as_str(),
|
|
||||||
state.no_water.to_string().as_bytes(),
|
|
||||||
);
|
|
||||||
let _ = board.mqtt_publish(
|
|
||||||
&config,
|
|
||||||
format!("/plant{}/Out of Work Hour", plant).as_str(),
|
|
||||||
state.out_of_work_hour.to_string().as_bytes(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for plant in 0..PLANT_COUNT {
|
for plant in 0..PLANT_COUNT {
|
||||||
let state = &plantstate[plant];
|
let state = &plantstate[plant];
|
||||||
@ -906,6 +901,133 @@ fn determine_next_plant(
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_plant_state(plantstate: &mut [PlantState; PLANT_COUNT], board: &mut std::sync::MutexGuard<'_, PlantCtrlBoard<'_>>, config: &Config){
|
||||||
|
for plant in 0..PLANT_COUNT {
|
||||||
|
let state = &plantstate[plant];
|
||||||
|
let plant_config = config.plants[plant];
|
||||||
|
|
||||||
|
let last_time = board.last_pump_time(plant);
|
||||||
|
let europe_time = last_time.with_timezone(&Berlin);
|
||||||
|
if europe_time.year() > 2023 {
|
||||||
|
let time = europe_time.to_rfc3339();
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/last pump", plant+1).as_str(),
|
||||||
|
time.as_bytes(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/last pump", plant+1).as_str(),
|
||||||
|
"N/A".as_bytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
match state.next_pump {
|
||||||
|
Some(next) => {
|
||||||
|
let time = next.to_rfc3339();
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/next pump", plant+1).as_str(),
|
||||||
|
time.as_bytes(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/next pump", plant+1).as_str(),
|
||||||
|
"N/A".as_bytes(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Sensor A", plant+1).as_str(),
|
||||||
|
option_to_string(state.a).as_bytes(),
|
||||||
|
);
|
||||||
|
if plant_config.sensor_b {
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Sensor B", plant+1).as_str(),
|
||||||
|
option_to_string(state.b).as_bytes(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Sensor B", plant+1).as_str(),
|
||||||
|
"disabled".as_bytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if plant_config.sensor_p {
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Sensor P before", plant+1).as_str(),
|
||||||
|
option_to_string(state.p).as_bytes(),
|
||||||
|
);
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Sensor P after", plant+1).as_str(),
|
||||||
|
option_to_string(state.after_p).as_bytes(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Sensor P before", plant+1).as_str(),
|
||||||
|
"disabled".as_bytes(),
|
||||||
|
);
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Sensor P after", plant+1).as_str(),
|
||||||
|
"disabled".as_bytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Should water", plant+1).as_str(),
|
||||||
|
state.do_water.to_string().as_bytes(),
|
||||||
|
);
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Is frozen", plant+1).as_str(),
|
||||||
|
state.frozen.to_string().as_bytes(),
|
||||||
|
);
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Is dry", plant+1).as_str(),
|
||||||
|
state.dry.to_string().as_bytes(),
|
||||||
|
);
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Pump Error", plant+1).as_str(),
|
||||||
|
state.pump_error.to_string().as_bytes(),
|
||||||
|
);
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Pump Ineffective", plant+1).as_str(),
|
||||||
|
state.not_effective.to_string().as_bytes(),
|
||||||
|
);
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Is in Cooldown", plant+1).as_str(),
|
||||||
|
state.cooldown.to_string().as_bytes(),
|
||||||
|
);
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/No Water", plant+1).as_str(),
|
||||||
|
state.no_water.to_string().as_bytes(),
|
||||||
|
);
|
||||||
|
let _ = board.mqtt_publish(
|
||||||
|
&config,
|
||||||
|
format!("/plant{}/Out of Work Hour", plant+1).as_str(),
|
||||||
|
state.out_of_work_hour.to_string().as_bytes(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn wait_infinity(wait_type: WaitType, reboot_now: Arc<AtomicBool>) -> ! {
|
fn wait_infinity(wait_type: WaitType, reboot_now: Arc<AtomicBool>) -> ! {
|
||||||
let delay = match wait_type {
|
let delay = match wait_type {
|
||||||
WaitType::InitialConfig => 250_u32,
|
WaitType::InitialConfig => 250_u32,
|
||||||
|
@ -589,21 +589,18 @@ impl PlantCtrlBoardInteraction for PlantCtrlBoard<'_> {
|
|||||||
}
|
}
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
self.pump(i, true)?;
|
self.pump(i, true)?;
|
||||||
unsafe { vTaskDelay(500) };
|
unsafe { vTaskDelay(100) };
|
||||||
self.pump(i, false)?;
|
self.pump(i, false)?;
|
||||||
unsafe { vTaskDelay(500) };
|
unsafe { vTaskDelay(100) };
|
||||||
}
|
}
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
self.measure_moisture_hz(i, Sensor::A)?;
|
self.measure_moisture_hz(i, Sensor::A)?;
|
||||||
unsafe { vTaskDelay(500) };
|
|
||||||
}
|
}
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
self.measure_moisture_hz(i, Sensor::B)?;
|
self.measure_moisture_hz(i, Sensor::B)?;
|
||||||
unsafe { vTaskDelay(500) };
|
|
||||||
}
|
}
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
self.measure_moisture_hz(i, Sensor::PUMP)?;
|
self.measure_moisture_hz(i, Sensor::PUMP)?;
|
||||||
unsafe { vTaskDelay(500) };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -18,7 +18,9 @@ interface PlantConfig {
|
|||||||
pump_time_s: number,
|
pump_time_s: number,
|
||||||
pump_cooldown_min: number,
|
pump_cooldown_min: number,
|
||||||
pump_hour_start: number,
|
pump_hour_start: number,
|
||||||
pump_hour_end: number
|
pump_hour_end: number,
|
||||||
|
sensor_b: boolean,
|
||||||
|
sensor_p: boolean
|
||||||
}[]
|
}[]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +175,32 @@ let fromWrapper = (() => {
|
|||||||
holder.appendChild(text)
|
holder.appendChild(text)
|
||||||
text.innerHTML += "Pump Hour End"
|
text.innerHTML += "Pump Hour End"
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
let holder = document.createElement("div");
|
||||||
|
plant.appendChild(holder);
|
||||||
|
let input = document.createElement("input");
|
||||||
|
input.id = "plant_" + i + "_sensor_b";
|
||||||
|
input.type = "checkbox";
|
||||||
|
input.onchange = updateJson;
|
||||||
|
holder.appendChild(input)
|
||||||
|
|
||||||
|
let text = document.createElement("span");
|
||||||
|
holder.appendChild(text)
|
||||||
|
text.innerHTML += "Sensor B installed"
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let holder = document.createElement("div");
|
||||||
|
plant.appendChild(holder);
|
||||||
|
let input = document.createElement("input");
|
||||||
|
input.id = "plant_" + i + "_sensor_p";
|
||||||
|
input.type = "checkbox";
|
||||||
|
input.onchange = updateJson;
|
||||||
|
holder.appendChild(input)
|
||||||
|
|
||||||
|
let text = document.createElement("span");
|
||||||
|
holder.appendChild(text)
|
||||||
|
text.innerHTML += "Sensor P installed"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sync(current);
|
sync(current);
|
||||||
}
|
}
|
||||||
@ -208,6 +236,11 @@ let fromWrapper = (() => {
|
|||||||
plant_pump_hour_start.value = current.plants[i].pump_hour_start.toString();
|
plant_pump_hour_start.value = current.plants[i].pump_hour_start.toString();
|
||||||
let plant_pump_hour_end = document.getElementById("plant_" + i + "_pump_hour_end") as HTMLInputElement;
|
let plant_pump_hour_end = document.getElementById("plant_" + i + "_pump_hour_end") as HTMLInputElement;
|
||||||
plant_pump_hour_end.value = current.plants[i].pump_hour_end.toString();
|
plant_pump_hour_end.value = current.plants[i].pump_hour_end.toString();
|
||||||
|
|
||||||
|
let plant_sensor_b = document.getElementById("plant_" + i + "_sensor_b") as HTMLInputElement;
|
||||||
|
plant_sensor_b.checked = current.plants[i].sensor_b;
|
||||||
|
let plant_sensor_p = document.getElementById("plant_" + i + "_sensor_p") as HTMLInputElement;
|
||||||
|
plant_sensor_p.checked = current.plants[i].sensor_p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,6 +269,8 @@ let fromWrapper = (() => {
|
|||||||
let plant_pump_cooldown_min = document.getElementById("plant_" + i + "_pump_cooldown_min") as HTMLInputElement;
|
let plant_pump_cooldown_min = document.getElementById("plant_" + i + "_pump_cooldown_min") as HTMLInputElement;
|
||||||
let plant_pump_hour_start = document.getElementById("plant_" + i + "_pump_hour_start") as HTMLInputElement;
|
let plant_pump_hour_start = document.getElementById("plant_" + i + "_pump_hour_start") as HTMLInputElement;
|
||||||
let plant_pump_hour_end = document.getElementById("plant_" + i + "_pump_hour_end") as HTMLInputElement;
|
let plant_pump_hour_end = document.getElementById("plant_" + i + "_pump_hour_end") as HTMLInputElement;
|
||||||
|
let plant_sensor_b = document.getElementById("plant_" + i + "_sensor_b") as HTMLInputElement;
|
||||||
|
let plant_sensor_p = document.getElementById("plant_" + i + "_sensor_p") as HTMLInputElement;
|
||||||
|
|
||||||
current.plants[i] = {
|
current.plants[i] = {
|
||||||
mode: plant_mode.value,
|
mode: plant_mode.value,
|
||||||
@ -243,8 +278,9 @@ let fromWrapper = (() => {
|
|||||||
pump_time_s: +plant_pump_time_s.value,
|
pump_time_s: +plant_pump_time_s.value,
|
||||||
pump_cooldown_min: +plant_pump_cooldown_min.value,
|
pump_cooldown_min: +plant_pump_cooldown_min.value,
|
||||||
pump_hour_start: +plant_pump_hour_start.value,
|
pump_hour_start: +plant_pump_hour_start.value,
|
||||||
pump_hour_end: +plant_pump_hour_end.value
|
pump_hour_end: +plant_pump_hour_end.value,
|
||||||
|
sensor_b: plant_sensor_b.checked,
|
||||||
|
sensor_p: plant_sensor_p.checked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sync(current);
|
sync(current);
|
||||||
|
Loading…
Reference in New Issue
Block a user