Merge branch 'test_new_storage' of ssh://git.mannheim.ccc.de:1337/C3MA/PlantCtrl into test_new_storage
This commit is contained in:
@@ -96,6 +96,8 @@ pub enum BoardVersion {
|
|||||||
pub struct BoardHardware {
|
pub struct BoardHardware {
|
||||||
pub board: BoardVersion,
|
pub board: BoardVersion,
|
||||||
pub battery: BatteryBoardVersion,
|
pub battery: BatteryBoardVersion,
|
||||||
|
#[serde(default)]
|
||||||
|
pub pump_corrosion_protection: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default, Encode, Decode)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default, Encode, Decode)]
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ static mut CONSECUTIVE_WATERING_PLANT: [u32; PLANT_COUNT] = [0; PLANT_COUNT];
|
|||||||
static mut LOW_VOLTAGE_DETECTED: i8 = 0;
|
static mut LOW_VOLTAGE_DETECTED: i8 = 0;
|
||||||
#[esp_hal::ram(unstable(rtc_fast), unstable(persistent))]
|
#[esp_hal::ram(unstable(rtc_fast), unstable(persistent))]
|
||||||
static mut RESTART_TO_CONF: i8 = 0;
|
static mut RESTART_TO_CONF: i8 = 0;
|
||||||
|
#[esp_hal::ram(unstable(rtc_fast), unstable(persistent))]
|
||||||
|
static mut LAST_CORROSION_PROTECTION_CHECK_DAY: i8 = -1;
|
||||||
|
|
||||||
const NTP_SERVER: &str = "pool.ntp.org";
|
const NTP_SERVER: &str = "pool.ntp.org";
|
||||||
|
|
||||||
@@ -341,6 +343,14 @@ impl Esp<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub(crate) fn get_last_corrosion_protection_check_day(&self) -> i8 {
|
||||||
|
unsafe { LAST_CORROSION_PROTECTION_CHECK_DAY }
|
||||||
|
}
|
||||||
|
pub(crate) fn set_last_corrosion_protection_check_day(&mut self, day: i8) {
|
||||||
|
unsafe {
|
||||||
|
LAST_CORROSION_PROTECTION_CHECK_DAY = day;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn wifi_ap(&mut self, spawner: Spawner) -> FatResult<Stack<'static>> {
|
pub(crate) async fn wifi_ap(&mut self, spawner: Spawner) -> FatResult<Stack<'static>> {
|
||||||
let ssid = match self.load_config().await {
|
let ssid = match self.load_config().await {
|
||||||
@@ -595,6 +605,7 @@ impl Esp<'_> {
|
|||||||
} else {
|
} else {
|
||||||
RESTART_TO_CONF = 0;
|
RESTART_TO_CONF = 0;
|
||||||
}
|
}
|
||||||
|
LAST_CORROSION_PROTECTION_CHECK_DAY = -1;
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ impl Flash for SavegameFlashAdapter<'_> {
|
|||||||
data.len()
|
data.len()
|
||||||
);
|
);
|
||||||
let error = NorFlash::write(self.region, addr, data);
|
let error = NorFlash::write(self.region, addr, data);
|
||||||
if error.is_err() {
|
if let Err(err) = error {
|
||||||
error!("error {:?}", error.unwrap_err())
|
error!("error {:?}", err);
|
||||||
}
|
}
|
||||||
error.map_err(SavegameFlashError)
|
error.map_err(SavegameFlashError)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ impl InterceptorLogger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(&'static self) {
|
pub fn init(&'static self) {
|
||||||
match log::set_logger(self)
|
match log::set_logger(self).map(|()| log::set_max_level(LevelFilter::Info)) {
|
||||||
.map(|()| log::set_max_level(LevelFilter::Info)) {
|
|
||||||
Ok(()) => {}
|
Ok(()) => {}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Logger already set: {}", e);
|
error!("Logger already set: {}", e);
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ struct PumpInfo {
|
|||||||
median_current_ma: u16,
|
median_current_ma: u16,
|
||||||
max_current_ma: u16,
|
max_current_ma: u16,
|
||||||
min_current_ma: u16,
|
min_current_ma: u16,
|
||||||
|
error: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
@@ -129,7 +130,7 @@ pub struct PumpResult {
|
|||||||
median_current_ma: u16,
|
median_current_ma: u16,
|
||||||
max_current_ma: u16,
|
max_current_ma: u16,
|
||||||
min_current_ma: u16,
|
min_current_ma: u16,
|
||||||
error: bool,
|
error: String,
|
||||||
flow_value_ml: f32,
|
flow_value_ml: f32,
|
||||||
flow_value_count: i16,
|
flow_value_count: i16,
|
||||||
pump_time_s: u16,
|
pump_time_s: u16,
|
||||||
@@ -239,7 +240,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
println!("starting webserver");
|
println!("starting webserver");
|
||||||
|
|
||||||
let _ = http_server(reboot_now.clone(), stack);
|
let _ = http_server(reboot_now.clone(), stack);
|
||||||
wait_infinity(board, WaitType::MissingConfig, reboot_now.clone()).await;
|
wait_infinity(board, WaitType::MissingConfig, reboot_now.clone(), UTC).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut stack: OptionLock<Stack> = OptionLock::empty();
|
let mut stack: OptionLock<Stack> = OptionLock::empty();
|
||||||
@@ -276,7 +277,6 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
}),
|
}),
|
||||||
None => UTC, // Fallback to UTC if no timezone is set
|
None => UTC, // Fallback to UTC if no timezone is set
|
||||||
};
|
};
|
||||||
let _timezone = UTC;
|
|
||||||
|
|
||||||
let timezone_time = cur.with_timezone(&timezone);
|
let timezone_time = cur.with_timezone(&timezone);
|
||||||
info!(
|
info!(
|
||||||
@@ -321,7 +321,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
} else {
|
} else {
|
||||||
bail!("Network stack missing, hard abort")
|
bail!("Network stack missing, hard abort")
|
||||||
}
|
}
|
||||||
wait_infinity(board, WaitType::ConfigButton, reboot_now.clone()).await;
|
wait_infinity(board, WaitType::ConfigButton, reboot_now.clone(), timezone).await;
|
||||||
} else {
|
} else {
|
||||||
log(LogMessage::NormalRun, 0, 0, "", "");
|
log(LogMessage::NormalRun, 0, 0, "", "");
|
||||||
}
|
}
|
||||||
@@ -445,21 +445,40 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
board.board_hal.get_esp().last_pump_time(plant_id);
|
board.board_hal.get_esp().last_pump_time(plant_id);
|
||||||
//state.active = true;
|
//state.active = true;
|
||||||
|
|
||||||
pump_info(&mut board, plant_id, true, pump_ineffective, 0, 0, 0).await;
|
pump_info(&mut board, plant_id, true, pump_ineffective, 0, 0, 0, String::new()).await;
|
||||||
|
|
||||||
let result = do_secure_pump(&mut board, plant_id, plant_config, dry_run).await?;
|
let result = do_secure_pump(&mut board, plant_id, plant_config, dry_run).await;
|
||||||
|
match result {
|
||||||
|
Ok(state) => {
|
||||||
|
pump_info(
|
||||||
|
&mut board,
|
||||||
|
plant_id,
|
||||||
|
false,
|
||||||
|
pump_ineffective,
|
||||||
|
state.median_current_ma,
|
||||||
|
state.max_current_ma,
|
||||||
|
state.min_current_ma,
|
||||||
|
state.error,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
pump_info(
|
||||||
|
&mut board,
|
||||||
|
plant_id,
|
||||||
|
false,
|
||||||
|
pump_ineffective,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
format!("{err:?}"),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
//stop pump regardless of prior result//todo refactor to inner?
|
//stop pump regardless of prior result//todo refactor to inner?
|
||||||
board.board_hal.pump(plant_id, false).await?;
|
board.board_hal.pump(plant_id, false).await?;
|
||||||
pump_info(
|
|
||||||
&mut board,
|
|
||||||
plant_id,
|
|
||||||
false,
|
|
||||||
pump_ineffective,
|
|
||||||
result.median_current_ma,
|
|
||||||
result.max_current_ma,
|
|
||||||
result.min_current_ma,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
} else if !state.pump_in_timeout(plant_config, &timezone_time) {
|
} else if !state.pump_in_timeout(plant_config, &timezone_time) {
|
||||||
// plant does not need to be watered and is not in timeout
|
// plant does not need to be watered and is not in timeout
|
||||||
// -> reset consecutive pump count
|
// -> reset consecutive pump count
|
||||||
@@ -469,6 +488,33 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
.store_consecutive_pump_count(plant_id, 0);
|
.store_consecutive_pump_count(plant_id, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Pump corrosion protection: pulses each pump once a week for 2s around midday.
|
||||||
|
let last_check_day = board.board_hal.get_esp().get_last_corrosion_protection_check_day();
|
||||||
|
if board.board_hal.get_config().hardware.pump_corrosion_protection {
|
||||||
|
let current_day = timezone_time.weekday().number_from_monday() as i8;
|
||||||
|
let current_hour = timezone_time.hour();
|
||||||
|
|
||||||
|
// Monday (1) and around midday (11-13)
|
||||||
|
if current_day == 1 && (11..14).contains(¤t_hour) {
|
||||||
|
if last_check_day != current_day {
|
||||||
|
info!("Running pump corrosion protection");
|
||||||
|
for plant_id in 0..PLANT_COUNT {
|
||||||
|
let mut plant_config = board.board_hal.get_config().plants[plant_id].clone();
|
||||||
|
plant_config.pump_time_s = 2;
|
||||||
|
plant_config.pump_limit_ml = 1000; // high limit to ensure it runs for 2s
|
||||||
|
|
||||||
|
log(LogMessage::PumpPlant, (plant_id + 1) as u32, 2, "corrosion_prot", "");
|
||||||
|
let _ = do_secure_pump(&mut board, plant_id, &plant_config, dry_run).await;
|
||||||
|
let _ = board.board_hal.pump(plant_id, false).await;
|
||||||
|
}
|
||||||
|
board.board_hal.get_esp().set_last_corrosion_protection_check_day(current_day);
|
||||||
|
}
|
||||||
|
} else if last_check_day != current_day && current_day != 1 {
|
||||||
|
// Reset check day if it's a different day (and not Monday), so it can trigger again next week
|
||||||
|
board.board_hal.get_esp().set_last_corrosion_protection_check_day(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("state of charg");
|
info!("state of charg");
|
||||||
@@ -578,19 +624,18 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
.mqtt_publish("/deepsleep", "night 1h").await;
|
.mqtt_publish("/deepsleep", "night 1h").await;
|
||||||
60
|
60
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = board
|
let _ = board
|
||||||
.board_hal
|
.board_hal
|
||||||
.get_esp()
|
.get_esp()
|
||||||
.mqtt_publish("/state", "sleep")
|
.mqtt_publish("/state", "sleep")
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
info!("Go to sleep for {deep_sleep_duration_minutes} minutes");
|
info!("Go to sleep for {deep_sleep_duration_minutes} minutes");
|
||||||
|
|
||||||
//determine next event
|
//determine next event
|
||||||
//is light out of work trigger soon?
|
//is light out of work trigger soon?
|
||||||
//is battery low ??
|
//is battery low ??
|
||||||
//is deep sleep
|
//is deep sleep
|
||||||
//TODO
|
|
||||||
//mark_app_valid();
|
|
||||||
|
|
||||||
let stay_alive = MQTT_STAY_ALIVE.load(Ordering::Relaxed);
|
let stay_alive = MQTT_STAY_ALIVE.load(Ordering::Relaxed);
|
||||||
info!("Check stay alive, current state is {stay_alive}");
|
info!("Check stay alive, current state is {stay_alive}");
|
||||||
@@ -599,7 +644,7 @@ async fn safe_main(spawner: Spawner) -> FatResult<()> {
|
|||||||
let reboot_now = Arc::new(AtomicBool::new(false));
|
let reboot_now = Arc::new(AtomicBool::new(false));
|
||||||
if let Some(s) = stack.take() {
|
if let Some(s) = stack.take() {
|
||||||
spawner.spawn(http_server(reboot_now.clone(), s))?;
|
spawner.spawn(http_server(reboot_now.clone(), s))?;
|
||||||
wait_infinity(board, WaitType::MqttConfig, reboot_now.clone()).await;
|
wait_infinity(board, WaitType::MqttConfig, reboot_now.clone(), timezone).await;
|
||||||
} else {
|
} else {
|
||||||
bail!("Network Stack missing, hard abort");
|
bail!("Network Stack missing, hard abort");
|
||||||
}
|
}
|
||||||
@@ -628,7 +673,7 @@ pub async fn do_secure_pump(
|
|||||||
|
|
||||||
let mut current_collector = vec![0_u16; steps_in_50ms];
|
let mut current_collector = vec![0_u16; steps_in_50ms];
|
||||||
let mut flow_collector = vec![0_i16; steps_in_50ms];
|
let mut flow_collector = vec![0_i16; steps_in_50ms];
|
||||||
let mut error = false;
|
let mut error = String::new();
|
||||||
let mut first_error = true;
|
let mut first_error = true;
|
||||||
let mut pump_time_ms: u32 = 0;
|
let mut pump_time_ms: u32 = 0;
|
||||||
|
|
||||||
@@ -662,6 +707,7 @@ pub async fn do_secure_pump(
|
|||||||
&& high_current
|
&& high_current
|
||||||
&& current_ma > STARTUP_ABORT_CURRENT_MA
|
&& current_ma > STARTUP_ABORT_CURRENT_MA
|
||||||
{
|
{
|
||||||
|
let err_msg = format!("OverCurrent startup: {}mA", current_ma);
|
||||||
log(
|
log(
|
||||||
LogMessage::PumpOverCurrent,
|
LogMessage::PumpOverCurrent,
|
||||||
plant_id as u32 + 1,
|
plant_id as u32 + 1,
|
||||||
@@ -669,8 +715,9 @@ pub async fn do_secure_pump(
|
|||||||
plant_config.max_pump_current_ma.to_string().as_str(),
|
plant_config.max_pump_current_ma.to_string().as_str(),
|
||||||
step.to_string().as_str(),
|
step.to_string().as_str(),
|
||||||
);
|
);
|
||||||
error = true;
|
error = err_msg;
|
||||||
} else if high_current && first_error {
|
} else if high_current && first_error {
|
||||||
|
let err_msg = format!("OverCurrent: {}mA", current_ma);
|
||||||
log(
|
log(
|
||||||
LogMessage::PumpOverCurrent,
|
LogMessage::PumpOverCurrent,
|
||||||
plant_id as u32 + 1,
|
plant_id as u32 + 1,
|
||||||
@@ -681,13 +728,14 @@ pub async fn do_secure_pump(
|
|||||||
board.board_hal.general_fault(true).await;
|
board.board_hal.general_fault(true).await;
|
||||||
board.board_hal.fault(plant_id, true).await?;
|
board.board_hal.fault(plant_id, true).await?;
|
||||||
if !plant_config.ignore_current_error {
|
if !plant_config.ignore_current_error {
|
||||||
error = true;
|
error = err_msg;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
first_error = false;
|
first_error = false;
|
||||||
}
|
}
|
||||||
let low_current = current_ma < plant_config.min_pump_current_ma;
|
let low_current = current_ma < plant_config.min_pump_current_ma;
|
||||||
if low_current && first_error {
|
if low_current && first_error {
|
||||||
|
let err_msg = format!("OpenLoop: {}mA", current_ma);
|
||||||
log(
|
log(
|
||||||
LogMessage::PumpOpenLoopCurrent,
|
LogMessage::PumpOpenLoopCurrent,
|
||||||
plant_id as u32 + 1,
|
plant_id as u32 + 1,
|
||||||
@@ -698,7 +746,7 @@ pub async fn do_secure_pump(
|
|||||||
board.board_hal.general_fault(true).await;
|
board.board_hal.general_fault(true).await;
|
||||||
board.board_hal.fault(plant_id, true).await?;
|
board.board_hal.fault(plant_id, true).await?;
|
||||||
if !plant_config.ignore_current_error {
|
if !plant_config.ignore_current_error {
|
||||||
error = true;
|
error = err_msg;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
first_error = false;
|
first_error = false;
|
||||||
@@ -707,6 +755,7 @@ pub async fn do_secure_pump(
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
if !plant_config.ignore_current_error {
|
if !plant_config.ignore_current_error {
|
||||||
info!("Error getting pump current: {err}");
|
info!("Error getting pump current: {err}");
|
||||||
|
let err_msg = format!("MissingSensor: {err:?}");
|
||||||
log(
|
log(
|
||||||
LogMessage::PumpMissingSensorCurrent,
|
LogMessage::PumpMissingSensorCurrent,
|
||||||
plant_id as u32,
|
plant_id as u32,
|
||||||
@@ -714,7 +763,7 @@ pub async fn do_secure_pump(
|
|||||||
"",
|
"",
|
||||||
"",
|
"",
|
||||||
);
|
);
|
||||||
error = true;
|
error = err_msg;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
error!("Error getting pump current: {err}");
|
error!("Error getting pump current: {err}");
|
||||||
@@ -740,6 +789,9 @@ pub async fn do_secure_pump(
|
|||||||
Timer::after(sleep_time).await;
|
Timer::after(sleep_time).await;
|
||||||
pump_time_ms += 50;
|
pump_time_ms += 50;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
//noticable dummy value
|
||||||
|
pump_time_ms = 1337;
|
||||||
}
|
}
|
||||||
board.board_hal.get_tank_sensor()?.stop_flow_meter();
|
board.board_hal.get_tank_sensor()?.stop_flow_meter();
|
||||||
let final_flow_value = board.board_hal.get_tank_sensor()?.get_flow_meter_value();
|
let final_flow_value = board.board_hal.get_tank_sensor()?.get_flow_meter_value();
|
||||||
@@ -907,6 +959,7 @@ async fn pump_info(
|
|||||||
median_current_ma: u16,
|
median_current_ma: u16,
|
||||||
max_current_ma: u16,
|
max_current_ma: u16,
|
||||||
min_current_ma: u16,
|
min_current_ma: u16,
|
||||||
|
error: String,
|
||||||
) {
|
) {
|
||||||
let pump_info = PumpInfo {
|
let pump_info = PumpInfo {
|
||||||
enabled: pump_active,
|
enabled: pump_active,
|
||||||
@@ -914,6 +967,7 @@ async fn pump_info(
|
|||||||
median_current_ma,
|
median_current_ma,
|
||||||
max_current_ma,
|
max_current_ma,
|
||||||
min_current_ma,
|
min_current_ma,
|
||||||
|
error,
|
||||||
};
|
};
|
||||||
let pump_topic = format!("/pump{}", plant_id + 1);
|
let pump_topic = format!("/pump{}", plant_id + 1);
|
||||||
|
|
||||||
@@ -975,6 +1029,7 @@ async fn wait_infinity(
|
|||||||
board: MutexGuard<'_, CriticalSectionRawMutex, HAL<'static>>,
|
board: MutexGuard<'_, CriticalSectionRawMutex, HAL<'static>>,
|
||||||
wait_type: WaitType,
|
wait_type: WaitType,
|
||||||
reboot_now: Arc<AtomicBool>,
|
reboot_now: Arc<AtomicBool>,
|
||||||
|
timezone: Tz,
|
||||||
) -> ! {
|
) -> ! {
|
||||||
//since we force to have the lock when entering, we can release it to ensure the caller does not forget to dispose of it
|
//since we force to have the lock when entering, we can release it to ensure the caller does not forget to dispose of it
|
||||||
drop(board);
|
drop(board);
|
||||||
@@ -984,6 +1039,7 @@ async fn wait_infinity(
|
|||||||
let mut pattern_step = 0;
|
let mut pattern_step = 0;
|
||||||
let serial_config_receive = AtomicBool::new(false);
|
let serial_config_receive = AtomicBool::new(false);
|
||||||
let mut suppress_further_mppt_error = false;
|
let mut suppress_further_mppt_error = false;
|
||||||
|
let mut last_mqtt_update: Option<Instant> = None;
|
||||||
|
|
||||||
// Long-press exit (for webserver config modes): hold boot button for 5 seconds.
|
// Long-press exit (for webserver config modes): hold boot button for 5 seconds.
|
||||||
let mut exit_hold_started: Option<Instant> = None;
|
let mut exit_hold_started: Option<Instant> = None;
|
||||||
@@ -1060,6 +1116,22 @@ async fn wait_infinity(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MQTT updates in config mode
|
||||||
|
let now = Instant::now();
|
||||||
|
if last_mqtt_update.is_none()
|
||||||
|
|| now.duration_since(last_mqtt_update.unwrap_or(Instant::from_secs(0)))
|
||||||
|
>= Duration::from_secs(60)
|
||||||
|
{
|
||||||
|
let cur = board.board_hal.get_time().await;
|
||||||
|
let timezone_time = cur.with_timezone(&timezone);
|
||||||
|
|
||||||
|
let esp = board.board_hal.get_esp();
|
||||||
|
esp.mqtt_publish("/firmware/state", "config").await;
|
||||||
|
esp.mqtt_publish("/firmware/last_online", &timezone_time.to_rfc3339())
|
||||||
|
.await;
|
||||||
|
last_mqtt_update = Some(now);
|
||||||
|
}
|
||||||
|
|
||||||
// Skip default blink code when a progress display is active
|
// Skip default blink code when a progress display is active
|
||||||
if !PROGRESS_ACTIVE.load(Ordering::Relaxed) {
|
if !PROGRESS_ACTIVE.load(Ordering::Relaxed) {
|
||||||
match wait_type {
|
match wait_type {
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ export enum BoardVersion {
|
|||||||
export interface BoardHardware {
|
export interface BoardHardware {
|
||||||
board: BoardVersion,
|
board: BoardVersion,
|
||||||
battery: BatteryBoardVersion,
|
battery: BatteryBoardVersion,
|
||||||
|
pump_corrosion_protection: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PlantControllerConfig {
|
export interface PlantControllerConfig {
|
||||||
|
|||||||
@@ -18,3 +18,7 @@
|
|||||||
<select class="boardvalue" id="hardware_battery_value">
|
<select class="boardvalue" id="hardware_battery_value">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flexcontainer">
|
||||||
|
<div class="boardkey">Pump corrosion protection (weekly)</div>
|
||||||
|
<input type="checkbox" id="hardware_pump_corrosion_protection">
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import {BatteryBoardVersion, BoardHardware, BoardVersion} from "./api";
|
|||||||
export class HardwareConfigView {
|
export class HardwareConfigView {
|
||||||
private readonly hardware_board_value: HTMLSelectElement;
|
private readonly hardware_board_value: HTMLSelectElement;
|
||||||
private readonly hardware_battery_value: HTMLSelectElement;
|
private readonly hardware_battery_value: HTMLSelectElement;
|
||||||
|
private readonly hardware_pump_corrosion_protection: HTMLInputElement;
|
||||||
constructor(controller:Controller){
|
constructor(controller:Controller){
|
||||||
(document.getElementById("hardwareview") as HTMLElement).innerHTML = require('./hardware.html') as string;
|
(document.getElementById("hardwareview") as HTMLElement).innerHTML = require('./hardware.html') as string;
|
||||||
|
|
||||||
@@ -29,17 +30,22 @@ export class HardwareConfigView {
|
|||||||
option.innerText = version.toString();
|
option.innerText = version.toString();
|
||||||
this.hardware_battery_value.appendChild(option);
|
this.hardware_battery_value.appendChild(option);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
this.hardware_pump_corrosion_protection = document.getElementById("hardware_pump_corrosion_protection") as HTMLInputElement;
|
||||||
|
this.hardware_pump_corrosion_protection.onchange = controller.configChanged
|
||||||
}
|
}
|
||||||
|
|
||||||
setConfig(hardware: BoardHardware) {
|
setConfig(hardware: BoardHardware) {
|
||||||
this.hardware_board_value.value = hardware.board.toString()
|
this.hardware_board_value.value = hardware.board.toString()
|
||||||
this.hardware_battery_value.value = hardware.battery.toString()
|
this.hardware_battery_value.value = hardware.battery.toString()
|
||||||
|
this.hardware_pump_corrosion_protection.checked = hardware.pump_corrosion_protection
|
||||||
}
|
}
|
||||||
|
|
||||||
getConfig(): BoardHardware {
|
getConfig(): BoardHardware {
|
||||||
return {
|
return {
|
||||||
board : BoardVersion[this.hardware_board_value.value as keyof typeof BoardVersion],
|
board : BoardVersion[this.hardware_board_value.value as keyof typeof BoardVersion],
|
||||||
battery : BatteryBoardVersion[this.hardware_battery_value.value as keyof typeof BatteryBoardVersion],
|
battery : BatteryBoardVersion[this.hardware_battery_value.value as keyof typeof BatteryBoardVersion],
|
||||||
|
pump_corrosion_protection : this.hardware_pump_corrosion_protection.checked,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user