fmt and mqtt workarounds

This commit is contained in:
2024-04-22 13:03:42 +02:00
parent 82bc9ed66d
commit 86c6bb5a73
8 changed files with 7252 additions and 9559 deletions

View File

@@ -5,7 +5,11 @@ use chrono_tz::{Europe::Berlin, Tz};
use esp_idf_hal::delay::Delay;
use esp_idf_sys::{
esp_deep_sleep, esp_ota_get_app_partition_count, esp_ota_get_running_partition, esp_ota_get_state_partition, esp_ota_img_states_t, esp_ota_img_states_t_ESP_OTA_IMG_ABORTED, esp_ota_img_states_t_ESP_OTA_IMG_INVALID, esp_ota_img_states_t_ESP_OTA_IMG_NEW, esp_ota_img_states_t_ESP_OTA_IMG_PENDING_VERIFY, esp_ota_img_states_t_ESP_OTA_IMG_UNDEFINED, esp_ota_img_states_t_ESP_OTA_IMG_VALID, esp_restart, vTaskDelay, CONFIG_FREERTOS_HZ
esp_deep_sleep, esp_ota_get_app_partition_count, esp_ota_get_running_partition,
esp_ota_get_state_partition, esp_ota_img_states_t, esp_ota_img_states_t_ESP_OTA_IMG_ABORTED,
esp_ota_img_states_t_ESP_OTA_IMG_INVALID, esp_ota_img_states_t_ESP_OTA_IMG_NEW,
esp_ota_img_states_t_ESP_OTA_IMG_PENDING_VERIFY, esp_ota_img_states_t_ESP_OTA_IMG_UNDEFINED,
esp_ota_img_states_t_ESP_OTA_IMG_VALID, esp_restart, vTaskDelay, CONFIG_FREERTOS_HZ,
};
use log::error;
use once_cell::sync::Lazy;
@@ -127,12 +131,9 @@ fn safe_main() -> anyhow::Result<()> {
println!("Partition count is {}", count);
let mut ota_state: esp_ota_img_states_t = 0;
let running_partition = unsafe { esp_ota_get_running_partition() };
let address = unsafe {
(*running_partition).address
};
let address = unsafe { (*running_partition).address };
println!("Partition address is {}", address);
let ota_state_string = unsafe {
esp_ota_get_state_partition(running_partition, &mut ota_state);
if ota_state == esp_ota_img_states_t_ESP_OTA_IMG_NEW {
@@ -237,10 +238,10 @@ fn safe_main() -> anyhow::Result<()> {
};
println!("attempting to connect wifi");
let mut ip_address: Option<String> = None;
let mut ip_address: Option<String> = None;
match board.wifi(wifi.ssid, wifi.password, 10000) {
Ok(ip_info) => {
ip_address = Some(ip_info.ip.to_string());
ip_address = Some(ip_info.ip.to_string());
online_mode = OnlineMode::Wifi;
}
Err(_) => {
@@ -298,16 +299,24 @@ fn safe_main() -> anyhow::Result<()> {
match ip_address {
Some(add_some) => {
let _ = board.mqtt_publish(&config, "/firmware/address", add_some.as_bytes());
},
}
None => {
let _ = board.mqtt_publish(&config, "/firmware/address", "N/A?".as_bytes());
},
}
}
let _ = board.mqtt_publish(&config, "/firmware/githash", git_hash.as_bytes());
let _ = board.mqtt_publish(&config, "/firmware/buildtime", build_timestamp.as_bytes());
let _ = board.mqtt_publish(&config, "/firmware/last_online", europe_time.to_rfc3339().as_bytes());
let _ = board.mqtt_publish(
&config,
"/firmware/last_online",
europe_time.to_rfc3339().as_bytes(),
);
let _ = board.mqtt_publish(&config, "/firmware/ota_state", ota_state_string.as_bytes());
let _ = board.mqtt_publish(&config, "/firmware/partition_address", format!("{:#06x}",address).as_bytes());
let _ = board.mqtt_publish(
&config,
"/firmware/partition_address",
format!("{:#06x}", address).as_bytes(),
);
let _ = board.mqtt_publish(&config, "/state", "online".as_bytes());
publish_battery_state(&mut board, &config);
@@ -318,15 +327,23 @@ fn safe_main() -> anyhow::Result<()> {
if tank_state.sensor_error {
let _ = board.mqtt_publish(&config, "/water/ml", "error".to_string().as_bytes());
} else {
let _ = board.mqtt_publish(&config, "/water/ml", tank_state.left_ml.to_string().as_bytes());
let _ = board.mqtt_publish(&config, "/water/enough_water", tank_state.enough_water.to_string().as_bytes());
let _ = board.mqtt_publish(&config, "/water/raw", tank_state.raw.to_string().as_bytes());
}
let _ = board.mqtt_publish(
&config,
"/water/ml",
tank_state.left_ml.to_string().as_bytes(),
);
let _ = board.mqtt_publish(
&config,
"/water/enough_water",
tank_state.enough_water.to_string().as_bytes(),
);
let _ =
board.mqtt_publish(&config, "/water/raw", tank_state.raw.to_string().as_bytes());
}
}
let mut water_frozen = false;
let mut temp:Option<f32> = None;
let mut temp: Option<f32> = None;
for _attempt in 0..5 {
let water_temperature = board.water_temperature_c();
match water_temperature {
@@ -346,25 +363,17 @@ fn safe_main() -> anyhow::Result<()> {
water_frozen = true;
}
if online_mode == OnlineMode::Online {
let _ = board.mqtt_publish(
&config,
"/water/temperature",
res.to_string().as_bytes(),
);
let _ =
board.mqtt_publish(&config, "/water/temperature", res.to_string().as_bytes());
}
},
}
None => {
if online_mode == OnlineMode::Online {
let _ = board.mqtt_publish(&config, "/water/temperature", "Error".as_bytes());
}
},
}
}
let mut plantstate = [PlantState {
..Default::default()
}; PLANT_COUNT];
@@ -527,40 +536,24 @@ fn safe_main() -> anyhow::Result<()> {
let deep_sleep_duration_minutes: u32 = if state_of_charge < 10 {
if online_mode == OnlineMode::Online {
let _ = board.mqtt_publish(
&config,
"/deepsleep",
"low Volt 12h".as_bytes(),
);
let _ = board.mqtt_publish(&config, "/deepsleep", "low Volt 12h".as_bytes());
}
12 * 60
} else if is_day {
if did_pump {
if online_mode == OnlineMode::Online {
let _ = board.mqtt_publish(
&config,
"/deepsleep",
"after pump".as_bytes(),
);
let _ = board.mqtt_publish(&config, "/deepsleep", "after pump".as_bytes());
}
0
} else {
if online_mode == OnlineMode::Online {
let _ = board.mqtt_publish(
&config,
"/deepsleep",
"normal 20m".as_bytes(),
);
let _ = board.mqtt_publish(&config, "/deepsleep", "normal 20m".as_bytes());
}
20
}
} else {
if online_mode == OnlineMode::Online {
let _ = board.mqtt_publish(
&config,
"/deepsleep",
"night 1h".as_bytes(),
);
let _ = board.mqtt_publish(&config, "/deepsleep", "night 1h".as_bytes());
}
60
};
@@ -568,7 +561,6 @@ fn safe_main() -> anyhow::Result<()> {
let _ = board.mqtt_publish(&config, "/state", "sleep".as_bytes());
}
//determine next event
//is light out of work trigger soon?
//is battery low ??
@@ -853,18 +845,31 @@ fn determine_state_target_moisture_for_plant(
state.dry = true;
if tank_state.sensor_error && !config.tank_allow_pumping_if_sensor_error {
//ignore is ok
}
else if !tank_state.enough_water {
} else if !tank_state.enough_water {
state.no_water = true;
}
}
let duration = TimeDelta::try_minutes(plant_config.pump_cooldown_min as i64).unwrap();
let next_pump = board.last_pump_time(plant) + duration;
if next_pump > cur {
let europe_time = next_pump.with_timezone(&Berlin);
state.next_pump = Some(europe_time);
state.cooldown = true;
let last_pump = board.last_pump_time(plant);
match last_pump {
Some(last_pump) => {
let next_pump = last_pump + duration;
if next_pump > cur {
let europe_time = next_pump.with_timezone(&Berlin);
state.next_pump = Some(europe_time);
state.cooldown = true;
}
}
None => {
println!(
"Could not restore last pump for plant {}, restoring",
plant + 1
);
board.store_last_pump_time(plant, DateTime::from_timestamp_millis(0).unwrap());
state.pump_error = true;
}
}
if !in_time_range(
cur,
plant_config.pump_hour_start,
@@ -884,6 +889,100 @@ fn determine_state_target_moisture_for_plant(
}
}
fn determine_state_timer_only_for_plant(
board: &mut std::sync::MutexGuard<'_, PlantCtrlBoard<'_>>,
plant: usize,
state: &mut PlantState,
config: &Config,
tank_state: &TankState,
water_frozen: bool,
cur: DateTime<Tz>,
) {
let plant_config = &config.plants[plant];
let duration = TimeDelta::try_minutes(plant_config.pump_cooldown_min as i64).unwrap();
let last_pump = board.last_pump_time(plant);
match last_pump {
Some(last_pump) => {
let next_pump = last_pump + duration;
if next_pump > cur {
let europe_time = next_pump.with_timezone(&Berlin);
state.next_pump = Some(europe_time);
state.cooldown = true;
} else {
if water_frozen {
state.frozen = true;
} else {
if tank_state.sensor_error && !config.tank_allow_pumping_if_sensor_error {
state.do_water = true;
} else if !tank_state.enough_water {
state.no_water = true;
}
}
}
}
None => {
println!(
"Could not restore last pump for plant {}, restoring",
plant + 1
);
board.store_last_pump_time(plant, DateTime::from_timestamp_millis(0).unwrap());
state.pump_error = true;
}
}
}
fn determine_state_timer_and_deadzone_for_plant(
board: &mut std::sync::MutexGuard<'_, PlantCtrlBoard<'_>>,
plant: usize,
state: &mut PlantState,
config: &Config,
tank_state: &TankState,
water_frozen: bool,
cur: DateTime<Tz>,
) {
let plant_config = &config.plants[plant];
let duration = TimeDelta::try_minutes(plant_config.pump_cooldown_min as i64).unwrap();
let last_pump = board.last_pump_time(plant);
match last_pump {
Some(last_pump) => {
let next_pump = last_pump + duration;
if next_pump > cur {
let europe_time = next_pump.with_timezone(&Berlin);
state.next_pump = Some(europe_time);
state.cooldown = true;
}
if !in_time_range(
cur,
plant_config.pump_hour_start,
plant_config.pump_hour_end,
) {
state.out_of_work_hour = true;
}
if !state.cooldown && !state.out_of_work_hour {
if water_frozen {
state.frozen = true;
} else {
if tank_state.sensor_error && !config.tank_allow_pumping_if_sensor_error {
state.do_water = true;
} else if !tank_state.enough_water {
state.no_water = true;
}
}
}
}
None => {
println!(
"Could not restore last pump for plant {}, restoring",
plant + 1
);
board.store_last_pump_time(plant, DateTime::from_timestamp_millis(0).unwrap());
state.pump_error = true;
}
}
}
fn determine_next_plant(
plantstate: &mut [PlantState; PLANT_COUNT],
cur: DateTime<Tz>,
@@ -909,42 +1008,26 @@ fn determine_next_plant(
);
}
config::Mode::TimerOnly => {
let duration = TimeDelta::try_minutes(plant_config.pump_cooldown_min as i64).unwrap();
let next_pump = board.last_pump_time(plant) + duration;
if next_pump > cur {
let europe_time = next_pump.with_timezone(&Berlin);
state.next_pump = Some(europe_time);
state.cooldown = true;
} else {
if water_frozen {
state.frozen = true;
} else {
state.do_water = true;
}
}
determine_state_timer_only_for_plant(
board,
plant,
state,
config,
tank_state,
water_frozen,
cur,
);
}
config::Mode::TimerAndDeadzone => {
let duration = TimeDelta::try_minutes(plant_config.pump_cooldown_min as i64).unwrap();
let next_pump = board.last_pump_time(plant) + duration;
if next_pump > cur {
let europe_time = next_pump.with_timezone(&Berlin);
state.next_pump = Some(europe_time);
state.cooldown = true;
}
if !in_time_range(
determine_state_timer_and_deadzone_for_plant(
board,
plant,
state,
config,
tank_state,
water_frozen,
cur,
plant_config.pump_hour_start,
plant_config.pump_hour_end,
) {
state.out_of_work_hour = true;
}
if !state.cooldown && !state.out_of_work_hour {
if water_frozen {
state.frozen = true;
} else {
state.do_water = true;
}
}
);
}
}
@@ -995,20 +1078,31 @@ fn update_plant_state(
);
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 last_time {
Some(last_time) => {
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(),
);
}
}
None => {
let _ = board.mqtt_publish(
&config,
format!("/plant{}/last pump", plant + 1).as_str(),
"N/A".as_bytes(),
);
}
}
match state.next_pump {
@@ -1121,8 +1215,6 @@ fn update_plant_state(
format!("/plant{}/consecutive pump count", plant + 1).as_str(),
state.consecutive_pump_count.to_string().as_bytes(),
);
}
}
@@ -1171,13 +1263,13 @@ fn main() {
Ok(_) => {
println!("Main app finished, restarting");
unsafe { esp_restart() };
},
}
Err(err) => {
println!("Failed main {}", err);
let rollback_successful = rollback_and_reboot();
println!("Failed to rollback :(");
rollback_successful.unwrap();
},
}
}
}
//error codes