it's alive
This commit is contained in:
596
rust/src/main.rs
596
rust/src/main.rs
@@ -5,6 +5,10 @@
|
||||
reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
|
||||
holding buffers for the duration of a data transfer."
|
||||
)]
|
||||
|
||||
esp_bootloader_esp_idf::esp_app_desc!();
|
||||
use esp_backtrace as _;
|
||||
|
||||
use crate::config::PlantConfig;
|
||||
use crate::{
|
||||
config::BoardVersion::INITIAL,
|
||||
@@ -16,24 +20,25 @@ use alloc::borrow::ToOwned;
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::sync::Arc;
|
||||
use alloc::{format, vec};
|
||||
use core::any::Any;
|
||||
use anyhow::{bail, Context};
|
||||
use chrono::{DateTime, Datelike, Timelike, Utc};
|
||||
use chrono_tz::Tz::{self, UTC};
|
||||
use chrono_tz::Tz::{self};
|
||||
use core::sync::atomic::Ordering;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_sync::blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex};
|
||||
use embassy_sync::lazy_lock::LazyLock;
|
||||
use embassy_sync::mutex::Mutex;
|
||||
use embassy_sync::mutex::MutexGuard;
|
||||
use embassy_time::Timer;
|
||||
use esp_hal::{clock::CpuClock, delay::Delay, timer::systimer::SystemTimer};
|
||||
use esp_println::logger;
|
||||
use esp_println::{logger, println};
|
||||
use hal::battery::BatteryState;
|
||||
use log::{log, LogMessage};
|
||||
use plant_state::PlantState;
|
||||
use portable_atomic::AtomicBool;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tank::*;
|
||||
use crate::tank::{TankError, WATER_FROZEN_THRESH};
|
||||
|
||||
//use tank::*;
|
||||
mod config;
|
||||
mod hal;
|
||||
mod log;
|
||||
@@ -44,7 +49,9 @@ extern crate alloc;
|
||||
//mod webserver;
|
||||
|
||||
pub static BOARD_ACCESS: LazyLock<Mutex<CriticalSectionRawMutex, HAL>> =
|
||||
LazyLock::new(|| PlantHal::create().unwrap());
|
||||
LazyLock::new(|| {
|
||||
PlantHal::create().unwrap()
|
||||
});
|
||||
pub static STAY_ALIVE: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, PartialEq)]
|
||||
@@ -163,10 +170,10 @@ async fn safe_main() -> anyhow::Result<()> {
|
||||
//};
|
||||
//log(LogMessage::PartitionState, 0, 0, "", ota_state_string);
|
||||
let ota_state_string = "unknown";
|
||||
|
||||
println!("faul led");
|
||||
let mut board = BOARD_ACCESS.get().lock().await;
|
||||
board.board_hal.general_fault(false).await;
|
||||
|
||||
println!("faul led2");
|
||||
let cur = board
|
||||
.board_hal
|
||||
.get_rtc_module()
|
||||
@@ -204,7 +211,7 @@ async fn safe_main() -> anyhow::Result<()> {
|
||||
board.board_hal.get_esp().set_restart_to_conf(false);
|
||||
} else if board.board_hal.get_esp().mode_override_pressed() {
|
||||
board.board_hal.general_fault(true).await;
|
||||
log(LogMessage::ConfigModeButtonOverride, 0, 0, "", "");
|
||||
log(LogMessage::ConfigModeButtonOverride, 0, 0, "", "").await;
|
||||
for _i in 0..5 {
|
||||
board.board_hal.general_fault(true).await;
|
||||
Timer::after_millis(100).await;
|
||||
@@ -251,19 +258,21 @@ async fn safe_main() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
let timezone = match &board.board_hal.get_config().timezone {
|
||||
Some(tz_str) => tz_str.parse::<Tz>().unwrap_or_else(|_| {
|
||||
info!("Invalid timezone '{}', falling back to UTC", tz_str);
|
||||
UTC
|
||||
}),
|
||||
None => UTC, // Fallback to UTC if no timezone is set
|
||||
};
|
||||
|
||||
let timezone_time = cur.with_timezone(&timezone);
|
||||
// let timezone = match &board.board_hal.get_config().timezone {
|
||||
// Some(tz_str) => tz_str.parse::<Tz>().unwrap_or_else(|_| {
|
||||
// info!("Invalid timezone '{}', falling back to UTC", tz_str);
|
||||
// UTC
|
||||
// }),
|
||||
// None => UTC, // Fallback to UTC if no timezone is set
|
||||
// };
|
||||
let timezone = Tz::UTC;
|
||||
|
||||
let timezone_time = cur;//TODO.with_timezone(&timezone);
|
||||
info!(
|
||||
"Running logic at utc {} and {} {}",
|
||||
cur,
|
||||
timezone.name(),
|
||||
"todo timezone.name()",
|
||||
timezone_time
|
||||
);
|
||||
|
||||
@@ -273,7 +282,7 @@ async fn safe_main() -> anyhow::Result<()> {
|
||||
partition_address,
|
||||
ota_state_string,
|
||||
ip_address,
|
||||
timezone_time,
|
||||
&timezone_time.to_rfc3339(),
|
||||
)
|
||||
.await;
|
||||
publish_battery_state().await;
|
||||
@@ -294,9 +303,10 @@ async fn safe_main() -> anyhow::Result<()> {
|
||||
.to_string()
|
||||
.as_str(),
|
||||
"",
|
||||
);
|
||||
).await;
|
||||
|
||||
drop(board);
|
||||
//TODO must drop board here?
|
||||
//drop(board);
|
||||
|
||||
if to_config {
|
||||
//check if client or ap mode and init Wi-Fi
|
||||
@@ -307,52 +317,54 @@ async fn safe_main() -> anyhow::Result<()> {
|
||||
//let _webserver = httpd(reboot_now.clone());
|
||||
wait_infinity(WaitType::ConfigButton, reboot_now.clone()).await;
|
||||
} else {
|
||||
log(LogMessage::NormalRun, 0, 0, "", "");
|
||||
log(LogMessage::NormalRun, 0, 0, "", "").await;
|
||||
}
|
||||
|
||||
let dry_run = false;
|
||||
|
||||
let tank_state = determine_tank_state(&mut board);
|
||||
|
||||
if tank_state.is_enabled() {
|
||||
if let Some(err) = tank_state.got_error(&board.board_hal.get_config().tank) {
|
||||
match err {
|
||||
TankError::SensorDisabled => { /* unreachable */ }
|
||||
TankError::SensorMissing(raw_value_mv) => log(
|
||||
LogMessage::TankSensorMissing,
|
||||
raw_value_mv as u32,
|
||||
0,
|
||||
"",
|
||||
"",
|
||||
),
|
||||
TankError::SensorValueError { value, min, max } => log(
|
||||
LogMessage::TankSensorValueRangeError,
|
||||
min as u32,
|
||||
max as u32,
|
||||
&format!("{}", value),
|
||||
"",
|
||||
),
|
||||
TankError::BoardError(err) => {
|
||||
log(LogMessage::TankSensorBoardError, 0, 0, "", &err.to_string())
|
||||
}
|
||||
}
|
||||
// disabled cannot trigger this because of wrapping if is_enabled
|
||||
board.board_hal.general_fault(true);
|
||||
} else if tank_state
|
||||
.warn_level(&board.board_hal.get_config().tank)
|
||||
.is_ok_and(|warn| warn)
|
||||
{
|
||||
log(LogMessage::TankWaterLevelLow, 0, 0, "", "");
|
||||
board.board_hal.general_fault(true);
|
||||
}
|
||||
}
|
||||
//
|
||||
// let tank_state = determine_tank_state(&mut board);
|
||||
//
|
||||
// if tank_state.is_enabled() {
|
||||
// if let Some(err) = tank_state.got_error(&board.board_hal.get_config().tank) {
|
||||
// match err {
|
||||
// TankError::SensorDisabled => { /* unreachable */ }
|
||||
// TankError::SensorMissing(raw_value_mv) => log(
|
||||
// LogMessage::TankSensorMissing,
|
||||
// raw_value_mv as u32,
|
||||
// 0,
|
||||
// "",
|
||||
// "",
|
||||
// ).await,
|
||||
// TankError::SensorValueError { value, min, max } => log(
|
||||
// LogMessage::TankSensorValueRangeError,
|
||||
// min as u32,
|
||||
// max as u32,
|
||||
// &format!("{}", value),
|
||||
// "",
|
||||
// ).await,
|
||||
// TankError::BoardError(err) => {
|
||||
// log(LogMessage::TankSensorBoardError, 0, 0, "", &err.to_string()).await
|
||||
// }
|
||||
// }
|
||||
// // disabled cannot trigger this because of wrapping if is_enabled
|
||||
// board.board_hal.general_fault(true).await;
|
||||
// } else if tank_state
|
||||
// .warn_level(&board.board_hal.get_config().tank)
|
||||
// .is_ok_and(|warn| warn)
|
||||
// {
|
||||
// log(LogMessage::TankWaterLevelLow, 0, 0, "", "").await;
|
||||
// board.board_hal.general_fault(true).await;
|
||||
// }
|
||||
// }
|
||||
|
||||
let mut water_frozen = false;
|
||||
let water_temp = board
|
||||
.board_hal
|
||||
.get_tank_sensor()
|
||||
.context("no sensor")
|
||||
.and_then(async |f| f.water_temperature_c().await);
|
||||
//TODO
|
||||
let water_temp = anyhow::Ok(12_f32);
|
||||
// board
|
||||
// .board_hal
|
||||
// .get_tank_sensor()
|
||||
// .context("no sensor")
|
||||
// .and_then(async |f| f.water_temperature_c().await);
|
||||
|
||||
if let Ok(res) = water_temp {
|
||||
if res < WATER_FROZEN_THRESH {
|
||||
@@ -360,80 +372,89 @@ async fn safe_main() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
publish_tank_state(&tank_state, &water_temp);
|
||||
//publish_tank_state(&tank_state, &water_temp).await;
|
||||
|
||||
let plantstate: [PlantState; PLANT_COUNT] =
|
||||
core::array::from_fn(|i| PlantState::read_hardware_state(i, &mut board).await);
|
||||
publish_plant_states(&timezone_time, &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 plantstate: [PlantState; PLANT_COUNT] = [
|
||||
PlantState::read_hardware_state(0, &mut board).await,
|
||||
PlantState::read_hardware_state(1, &mut board).await,
|
||||
PlantState::read_hardware_state(2, &mut board).await,
|
||||
PlantState::read_hardware_state(3, &mut board).await,
|
||||
PlantState::read_hardware_state(4, &mut board).await,
|
||||
PlantState::read_hardware_state(5, &mut board).await,
|
||||
PlantState::read_hardware_state(6, &mut board).await,
|
||||
PlantState::read_hardware_state(7, &mut board).await,
|
||||
];
|
||||
//publish_plant_states(&timezone_time.clone(), &plantstate).await;
|
||||
|
||||
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(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 is_day = board.board_hal.is_day();
|
||||
let state_of_charge = board
|
||||
@@ -455,67 +476,67 @@ async fn safe_main() -> anyhow::Result<()> {
|
||||
enabled: board.board_hal.get_config().night_lamp.enabled,
|
||||
..Default::default()
|
||||
};
|
||||
if light_state.enabled {
|
||||
light_state.is_day = is_day;
|
||||
light_state.out_of_work_hour = !in_time_range(
|
||||
&timezone_time,
|
||||
board
|
||||
.board_hal
|
||||
.get_config()
|
||||
.night_lamp
|
||||
.night_lamp_hour_start,
|
||||
board.board_hal.get_config().night_lamp.night_lamp_hour_end,
|
||||
);
|
||||
|
||||
if state_of_charge
|
||||
< board
|
||||
.board_hal
|
||||
.get_config()
|
||||
.night_lamp
|
||||
.low_soc_cutoff
|
||||
.into()
|
||||
{
|
||||
board.board_hal.get_esp().set_low_voltage_in_cycle();
|
||||
} else if state_of_charge
|
||||
> board
|
||||
.board_hal
|
||||
.get_config()
|
||||
.night_lamp
|
||||
.low_soc_restore
|
||||
.into()
|
||||
{
|
||||
board.board_hal.get_esp().clear_low_voltage_in_cycle();
|
||||
}
|
||||
light_state.battery_low = board.board_hal.get_esp().low_voltage_in_cycle();
|
||||
|
||||
if !light_state.out_of_work_hour {
|
||||
if board
|
||||
.board_hal
|
||||
.get_config()
|
||||
.night_lamp
|
||||
.night_lamp_only_when_dark
|
||||
{
|
||||
if !light_state.is_day {
|
||||
if light_state.battery_low {
|
||||
board.board_hal.light(false)?;
|
||||
} else {
|
||||
light_state.active = true;
|
||||
board.board_hal.light(true)?;
|
||||
}
|
||||
}
|
||||
} else if light_state.battery_low {
|
||||
board.board_hal.light(false)?;
|
||||
} else {
|
||||
light_state.active = true;
|
||||
board.board_hal.light(true)?;
|
||||
}
|
||||
} else {
|
||||
light_state.active = false;
|
||||
board.board_hal.light(false)?;
|
||||
}
|
||||
|
||||
info!("Lightstate is {:?}", light_state);
|
||||
}
|
||||
// if light_state.enabled {
|
||||
// light_state.is_day = is_day;
|
||||
// light_state.out_of_work_hour = !in_time_range(
|
||||
// &timezone_time,
|
||||
// board
|
||||
// .board_hal
|
||||
// .get_config()
|
||||
// .night_lamp
|
||||
// .night_lamp_hour_start,
|
||||
// board.board_hal.get_config().night_lamp.night_lamp_hour_end,
|
||||
// );
|
||||
//
|
||||
// if state_of_charge
|
||||
// < board
|
||||
// .board_hal
|
||||
// .get_config()
|
||||
// .night_lamp
|
||||
// .low_soc_cutoff
|
||||
// .into()
|
||||
// {
|
||||
// board.board_hal.get_esp().set_low_voltage_in_cycle();
|
||||
// } else if state_of_charge
|
||||
// > board
|
||||
// .board_hal
|
||||
// .get_config()
|
||||
// .night_lamp
|
||||
// .low_soc_restore
|
||||
// .into()
|
||||
// {
|
||||
// board.board_hal.get_esp().clear_low_voltage_in_cycle();
|
||||
// }
|
||||
// light_state.battery_low = board.board_hal.get_esp().low_voltage_in_cycle();
|
||||
//
|
||||
// if !light_state.out_of_work_hour {
|
||||
// if board
|
||||
// .board_hal
|
||||
// .get_config()
|
||||
// .night_lamp
|
||||
// .night_lamp_only_when_dark
|
||||
// {
|
||||
// if !light_state.is_day {
|
||||
// if light_state.battery_low {
|
||||
// board.board_hal.light(false)?;
|
||||
// } else {
|
||||
// light_state.active = true;
|
||||
// board.board_hal.light(true)?;
|
||||
// }
|
||||
// }
|
||||
// } else if light_state.battery_low {
|
||||
// board.board_hal.light(false)?;
|
||||
// } else {
|
||||
// light_state.active = true;
|
||||
// board.board_hal.light(true)?;
|
||||
// }
|
||||
// } else {
|
||||
// light_state.active = false;
|
||||
// board.board_hal.light(false)?;
|
||||
// }
|
||||
//
|
||||
// info!("Lightstate is {:?}", light_state);
|
||||
// }
|
||||
|
||||
match serde_json::to_string(&light_state) {
|
||||
Ok(state) => {
|
||||
@@ -596,24 +617,25 @@ pub async fn do_secure_pump(
|
||||
let mut pump_time_s = 0;
|
||||
let board = &mut BOARD_ACCESS.get().lock().await;
|
||||
if !dry_run {
|
||||
board
|
||||
.board_hal
|
||||
.get_tank_sensor()
|
||||
.unwrap()
|
||||
.reset_flow_meter();
|
||||
board
|
||||
.board_hal
|
||||
.get_tank_sensor()
|
||||
.unwrap()
|
||||
.start_flow_meter();
|
||||
// board
|
||||
// .board_hal
|
||||
// .get_tank_sensor()
|
||||
// .unwrap()
|
||||
// .reset_flow_meter();
|
||||
// board
|
||||
// .board_hal
|
||||
// .get_tank_sensor()
|
||||
// .unwrap()
|
||||
// .start_flow_meter();
|
||||
board.board_hal.pump(plant_id, true).await?;
|
||||
Timer::after_millis(10).await;
|
||||
for step in 0..plant_config.pump_time_s as usize {
|
||||
let flow_value = board
|
||||
.board_hal
|
||||
.get_tank_sensor()
|
||||
.unwrap()
|
||||
.get_flow_meter_value();
|
||||
// let flow_value = board
|
||||
// .board_hal
|
||||
// .get_tank_sensor()
|
||||
// .unwrap()
|
||||
// .get_flow_meter_value();
|
||||
let flow_value = 1;
|
||||
flow_collector[step] = flow_value;
|
||||
let flow_value_ml = flow_value as f32 * board.board_hal.get_config().tank.ml_per_pulse;
|
||||
|
||||
@@ -691,12 +713,13 @@ pub async fn do_secure_pump(
|
||||
pump_time_s += 1;
|
||||
}
|
||||
}
|
||||
board.board_hal.get_tank_sensor().unwrap().stop_flow_meter();
|
||||
let final_flow_value = board
|
||||
.board_hal
|
||||
.get_tank_sensor()
|
||||
.unwrap()
|
||||
.get_flow_meter_value();
|
||||
// board.board_hal.get_tank_sensor().unwrap().stop_flow_meter();
|
||||
// let final_flow_value = board
|
||||
// .board_hal
|
||||
// .get_tank_sensor()
|
||||
// .unwrap()
|
||||
// .get_flow_meter_value();
|
||||
let final_flow_value = 12;
|
||||
let flow_value_ml = final_flow_value as f32 * board.board_hal.get_config().tank.ml_per_pulse;
|
||||
info!(
|
||||
"Final flow value is {} with {} ml",
|
||||
@@ -715,8 +738,42 @@ pub async fn do_secure_pump(
|
||||
}
|
||||
|
||||
async fn update_charge_indicator() {
|
||||
let board = BOARD_ACCESS.get().lock().await;
|
||||
let board = &mut BOARD_ACCESS.get().lock().await;
|
||||
//we have mppt controller, ask it for charging current
|
||||
// let tank_state = determine_tank_state(&mut board);
|
||||
//
|
||||
// if tank_state.is_enabled() {
|
||||
// if let Some(err) = tank_state.got_error(&board.board_hal.get_config().tank) {
|
||||
// match err {
|
||||
// TankError::SensorDisabled => { /* unreachable */ }
|
||||
// TankError::SensorMissing(raw_value_mv) => log(
|
||||
// LogMessage::TankSensorMissing,
|
||||
// raw_value_mv as u32,
|
||||
// 0,
|
||||
// "",
|
||||
// "",
|
||||
// ).await,
|
||||
// TankError::SensorValueError { value, min, max } => log(
|
||||
// LogMessage::TankSensorValueRangeError,
|
||||
// min as u32,
|
||||
// max as u32,
|
||||
// &format!("{}", value),
|
||||
// "",
|
||||
// ).await,
|
||||
// TankError::BoardError(err) => {
|
||||
// log(LogMessage::TankSensorBoardError, 0, 0, "", &err.to_string()).await
|
||||
// }
|
||||
// }
|
||||
// // disabled cannot trigger this because of wrapping if is_enabled
|
||||
// board.board_hal.general_fault(true).await;
|
||||
// } else if tank_state
|
||||
// .warn_level(&board.board_hal.get_config().tank)
|
||||
// .is_ok_and(|warn| warn)
|
||||
// {
|
||||
// log(LogMessage::TankWaterLevelLow, 0, 0, "", "").await;
|
||||
// board.board_hal.general_fault(true).await;
|
||||
// }
|
||||
// }
|
||||
if let Ok(current) = board.board_hal.get_mptt_current().await {
|
||||
let _ = board
|
||||
.board_hal
|
||||
@@ -726,7 +783,7 @@ async fn update_charge_indicator() {
|
||||
else if let Ok(charging) = board
|
||||
.board_hal
|
||||
.get_battery_monitor()
|
||||
.average_current_milli_ampere()
|
||||
.average_current_milli_ampere().await
|
||||
{
|
||||
let _ = board.board_hal.set_charge_indicator(charging > 20);
|
||||
} else {
|
||||
@@ -734,55 +791,55 @@ async fn update_charge_indicator() {
|
||||
let _ = board.board_hal.set_charge_indicator(false);
|
||||
}
|
||||
}
|
||||
//
|
||||
// async fn publish_tank_state(tank_state: &TankState, water_temp: &anyhow::Result<f32>) {
|
||||
// let board = &mut BOARD_ACCESS.get().lock().await;
|
||||
// match serde_json::to_string(
|
||||
// &tank_state.as_mqtt_info(&board.board_hal.get_config().tank, water_temp),
|
||||
// ) {
|
||||
// Ok(state) => {
|
||||
// let _ = board
|
||||
// .board_hal
|
||||
// .get_esp()
|
||||
// .mqtt_publish("/water", state.as_bytes());
|
||||
// }
|
||||
// Err(err) => {
|
||||
// info!("Error publishing tankstate {}", err);
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
async fn publish_tank_state(tank_state: &TankState, water_temp: &anyhow::Result<f32>) {
|
||||
let board = &mut BOARD_ACCESS.get().lock().await;
|
||||
match serde_json::to_string(
|
||||
&tank_state.as_mqtt_info(&board.board_hal.get_config().tank, water_temp),
|
||||
) {
|
||||
Ok(state) => {
|
||||
let _ = board
|
||||
.board_hal
|
||||
.get_esp()
|
||||
.mqtt_publish("/water", state.as_bytes());
|
||||
}
|
||||
Err(err) => {
|
||||
info!("Error publishing tankstate {}", err);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async fn publish_plant_states(timezone_time: &DateTime<Tz>, plantstate: &[PlantState; 8]) {
|
||||
let board = &mut BOARD_ACCESS.get().lock().await;
|
||||
for (plant_id, (plant_state, plant_conf)) in plantstate
|
||||
.iter()
|
||||
.zip(&board.board_hal.get_config().plants.clone())
|
||||
.enumerate()
|
||||
{
|
||||
match serde_json::to_string(&plant_state.to_mqtt_info(plant_conf, timezone_time)) {
|
||||
Ok(state) => {
|
||||
let plant_topic = format!("/plant{}", plant_id + 1);
|
||||
let _ = board
|
||||
.board_hal
|
||||
.get_esp()
|
||||
.mqtt_publish(&plant_topic, state.as_bytes())
|
||||
.await;
|
||||
//TODO? reduce speed as else messages will be dropped
|
||||
Timer::after_millis(200).await
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Error publishing plant state {}", err);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
// async fn publish_plant_states(timezone_time: &DateTime<Tz>, plantstate: &[PlantState; 8]) {
|
||||
// let board = &mut BOARD_ACCESS.get().lock().await;
|
||||
// for (plant_id, (plant_state, plant_conf)) in plantstate
|
||||
// .iter()
|
||||
// .zip(&board.board_hal.get_config().plants.clone())
|
||||
// .enumerate()
|
||||
// {
|
||||
// match serde_json::to_string(&plant_state.to_mqtt_info(plant_conf, timezone_time)) {
|
||||
// Ok(state) => {
|
||||
// let plant_topic = format!("/plant{}", plant_id + 1);
|
||||
// let _ = board
|
||||
// .board_hal
|
||||
// .get_esp()
|
||||
// .mqtt_publish(&plant_topic, state.as_bytes())
|
||||
// .await;
|
||||
// //TODO? reduce speed as else messages will be dropped
|
||||
// Timer::after_millis(200).await
|
||||
// }
|
||||
// Err(err) => {
|
||||
// error!("Error publishing plant state {}", err);
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
// }
|
||||
|
||||
async fn publish_firmware_info(
|
||||
version: VersionInfo,
|
||||
address: u32,
|
||||
ota_state_string: &str,
|
||||
ip_address: &String,
|
||||
timezone_time: DateTime<Tz>,
|
||||
timezone_time: &String,
|
||||
) {
|
||||
let board = &mut BOARD_ACCESS.get().lock().await;
|
||||
let _ = board
|
||||
@@ -802,7 +859,7 @@ async fn publish_firmware_info(
|
||||
.await;
|
||||
let _ = board.board_hal.get_esp().mqtt_publish(
|
||||
"/firmware/last_online",
|
||||
timezone_time.to_rfc3339().as_bytes(),
|
||||
timezone_time.as_bytes(),
|
||||
);
|
||||
let _ = board
|
||||
.board_hal
|
||||
@@ -821,7 +878,7 @@ async fn publish_firmware_info(
|
||||
}
|
||||
|
||||
async fn try_connect_wifi_sntp_mqtt() -> NetworkMode {
|
||||
let board = BOARD_ACCESS.get().lock().await;
|
||||
let board = &mut BOARD_ACCESS.get().lock().await;
|
||||
let nw_conf = &board.board_hal.get_config().network.clone();
|
||||
match board.board_hal.get_esp().wifi(nw_conf).await {
|
||||
Ok(ip_info) => {
|
||||
@@ -860,7 +917,7 @@ async fn try_connect_wifi_sntp_mqtt() -> NetworkMode {
|
||||
}
|
||||
Err(_) => {
|
||||
info!("Offline mode");
|
||||
board.board_hal.general_fault(true);
|
||||
board.board_hal.general_fault(true).await;
|
||||
NetworkMode::OFFLINE
|
||||
}
|
||||
}
|
||||
@@ -922,8 +979,8 @@ async fn publish_mppt_state() -> anyhow::Result<()> {
|
||||
}
|
||||
|
||||
async fn publish_battery_state() -> () {
|
||||
let board = BOARD_ACCESS.get().lock().await;
|
||||
let state = board.board_hal.get_battery_monitor().get_battery_state();
|
||||
let board = &mut BOARD_ACCESS.get().lock().await;
|
||||
let state = board.board_hal.get_battery_monitor().get_battery_state().await;
|
||||
if let Ok(serialized_battery_state_bytes) =
|
||||
serde_json::to_string(&state).map(|s| s.into_bytes())
|
||||
{
|
||||
@@ -995,13 +1052,10 @@ async fn wait_infinity(wait_type: WaitType, reboot_now: Arc<AtomicBool>) -> ! {
|
||||
async fn main(spawner: Spawner) {
|
||||
// intialize embassy
|
||||
logger::init_logger_from_env();
|
||||
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
||||
let peripherals = esp_hal::init(config);
|
||||
|
||||
esp_alloc::heap_allocator!(size: 64 * 1024);
|
||||
|
||||
let timer0 = SystemTimer::new(peripherals.SYSTIMER);
|
||||
esp_hal_embassy::init(timer0.alarm0);
|
||||
//force init here!
|
||||
let board = BOARD_ACCESS.get().lock().await;
|
||||
drop(board);
|
||||
println!("test");
|
||||
|
||||
info!("Embassy initialized!");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user