Merge branch 'develop' into housekeeping and clippy and spellcheck

This commit is contained in:
2025-06-20 23:59:14 +02:00
parent e7b6bda747
commit d059b7b1db
9 changed files with 135 additions and 141 deletions

View File

@@ -1,7 +1,7 @@
use crate::{
config::BoardVersion::INITIAL,
hal::{PlantHal, HAL, PLANT_COUNT},
webserver::webserver::httpd,
webserver::httpd,
};
use anyhow::bail;
use chrono::{DateTime, Datelike, Timelike, Utc};
@@ -12,7 +12,7 @@ use esp_idf_sys::{
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, vTaskDelay,
esp_ota_img_states_t_ESP_OTA_IMG_VALID,
};
use esp_ota::{mark_app_valid, rollback_and_reboot};
use hal::battery::BatteryState;
@@ -28,13 +28,12 @@ mod hal;
mod log;
mod plant_state;
mod tank;
mod webserver;
pub static BOARD_ACCESS: Lazy<Mutex<HAL>> = Lazy::new(|| PlantHal::create().unwrap());
pub static STAY_ALIVE: Lazy<AtomicBool> = Lazy::new(|| AtomicBool::new(false));
mod webserver {
pub mod webserver;
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
enum WaitType {
@@ -69,7 +68,7 @@ struct LightState {
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Default)]
///mqtt stuct to track pump activities
///mqtt struct to track pump activities
struct PumpInfo {
enabled: bool,
pump_ineffective: bool,
@@ -175,16 +174,7 @@ fn safe_main() -> anyhow::Result<()> {
}
println!("cur is {}", cur);
match board
.board_hal
.get_battery_monitor()
.average_current_milli_ampere()
{
Ok(charging) => {
let _ = board.board_hal.set_charge_indicator(charging > 20);
}
Err(_) => {}
}
update_charge_indicator(&mut board);
if board.board_hal.get_esp().get_restart_to_conf() {
log(LogMessage::ConfigModeSoftwareOverride, 0, 0, "", "");
@@ -265,7 +255,7 @@ fn safe_main() -> anyhow::Result<()> {
address,
ota_state_string,
&mut board,
&ip_address,
ip_address,
timezone_time,
);
publish_battery_state(&mut board);
@@ -426,7 +416,7 @@ fn safe_main() -> anyhow::Result<()> {
.board_hal
.get_battery_monitor()
.get_battery_state()
.unwrap_or(hal::battery::BatteryState::Unknown);
.unwrap_or(BatteryState::Unknown);
let mut light_state = LightState {
enabled: board.board_hal.get_config().night_lamp.enabled,
@@ -556,6 +546,26 @@ fn safe_main() -> anyhow::Result<()> {
.deep_sleep(1000 * 1000 * 60 * deep_sleep_duration_minutes as u64);
}
fn update_charge_indicator(board: &mut MutexGuard<HAL>) {
//we have mppt controller, ask it for charging current
if let Ok(current) = board.board_hal.get_mptt_current() {
let _ = board
.board_hal
.set_charge_indicator(current.as_milliamperes() > 20_f64);
}
//fallback to battery controller and ask it instead
else if let Ok(charging) = board
.board_hal
.get_battery_monitor()
.average_current_milli_ampere()
{
let _ = board.board_hal.set_charge_indicator(charging > 20);
} else {
//who knows
let _ = board.board_hal.set_charge_indicator(false);
}
}
fn obtain_tank_temperature(board: &mut MutexGuard<HAL>) -> anyhow::Result<f32> {
//multisample should be moved to water_temperature_c
let mut attempt = 1;
@@ -608,7 +618,7 @@ fn publish_plant_states(
.zip(&board.board_hal.get_config().plants.clone())
.enumerate()
{
match serde_json::to_string(&plant_state.to_mqtt_info(plant_conf, &timezone_time)) {
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
@@ -679,7 +689,7 @@ fn try_connect_wifi_sntp_mqtt(board: &mut MutexGuard<HAL>) -> NetworkMode {
SntpMode::OFFLINE
}
};
let mqtt_connected = if let Some(_) = board.board_hal.get_config().network.mqtt_url {
let mqtt_connected = if board.board_hal.get_config().network.mqtt_url.is_some() {
let nw_config = &board.board_hal.get_config().network.clone();
match board.board_hal.get_esp().mqtt(nw_config) {
Ok(_) => {
@@ -750,76 +760,59 @@ fn wait_infinity(wait_type: WaitType, reboot_now: Arc<AtomicBool>) -> ! {
let delay = wait_type.blink_pattern();
let mut led_count = 8;
let mut pattern_step = 0;
let delay_handle = Delay::new_default();
loop {
unsafe {
let mut board = BOARD_ACCESS.lock().unwrap();
let mut board = BOARD_ACCESS.lock().unwrap();
update_charge_indicator(&mut board);
//we have mppt controller, ask it for charging current
if let Ok(current) = board.board_hal.get_mptt_current() {
let _ = board.board_hal.set_charge_indicator(current.as_milliamperes() > 20_f64);
}
//fallback to battery controller and ask it instead
else if let Ok(charging) = board
.board_hal
.get_battery_monitor()
.average_current_milli_ampere()
{
let _ = board.board_hal.set_charge_indicator(charging > 20);
}
else {
//who knows
let _ = board.board_hal.set_charge_indicator(false);
}
match wait_type {
WaitType::MissingConfig => {
// Keep existing behavior: circular filling pattern
led_count %= 8;
led_count += 1;
for i in 0..8 {
let _ = board.board_hal.fault(i, i < led_count);
}
}
WaitType::ConfigButton => {
// Alternating pattern: 1010 1010 -> 0101 0101
pattern_step = (pattern_step + 1) % 2;
for i in 0..8 {
let _ = board.board_hal.fault(i, (i + pattern_step) % 2 == 0);
}
}
WaitType::MqttConfig => {
// Moving dot pattern
pattern_step = (pattern_step + 1) % 8;
for i in 0..8 {
let _ = board.board_hal.fault(i, i == pattern_step);
}
match wait_type {
WaitType::MissingConfig => {
// Keep existing behavior: circular filling pattern
led_count %= 8;
led_count += 1;
for i in 0..8 {
let _ = board.board_hal.fault(i, i < led_count);
}
}
board.board_hal.general_fault(true);
drop(board);
vTaskDelay(delay);
let mut board = BOARD_ACCESS.lock().unwrap();
board.board_hal.general_fault(false);
// Clear all LEDs
for i in 0..8 {
let _ = board.board_hal.fault(i, false);
WaitType::ConfigButton => {
// Alternating pattern: 1010 1010 -> 0101 0101
pattern_step = (pattern_step + 1) % 2;
for i in 0..8 {
let _ = board.board_hal.fault(i, (i + pattern_step) % 2 == 0);
}
}
drop(board);
vTaskDelay(delay);
WaitType::MqttConfig => {
// Moving dot pattern
pattern_step = (pattern_step + 1) % 8;
for i in 0..8 {
let _ = board.board_hal.fault(i, i == pattern_step);
}
}
}
if wait_type == WaitType::MqttConfig
&& !STAY_ALIVE.load(std::sync::atomic::Ordering::Relaxed)
{
reboot_now.store(true, std::sync::atomic::Ordering::Relaxed);
}
if reboot_now.load(std::sync::atomic::Ordering::Relaxed) {
//ensure clean http answer
Delay::new_default().delay_ms(500);
BOARD_ACCESS.lock().unwrap().board_hal.deep_sleep(1);
}
board.board_hal.general_fault(true);
drop(board);
//cannot use shared delay as that is inside the mutex here
delay_handle.delay_ms(delay);
let mut board = BOARD_ACCESS.lock().unwrap();
board.board_hal.general_fault(false);
// Clear all LEDs
for i in 0..8 {
let _ = board.board_hal.fault(i, false);
}
drop(board);
delay_handle.delay_ms(delay);
if wait_type == WaitType::MqttConfig
&& !STAY_ALIVE.load(std::sync::atomic::Ordering::Relaxed)
{
reboot_now.store(true, std::sync::atomic::Ordering::Relaxed);
}
if reboot_now.load(std::sync::atomic::Ordering::Relaxed) {
//ensure clean http answer
Delay::new_default().delay_ms(500);
BOARD_ACCESS.lock().unwrap().board_hal.deep_sleep(1);
}
}
}
@@ -827,7 +820,7 @@ fn wait_infinity(wait_type: WaitType, reboot_now: Arc<AtomicBool>) -> ! {
fn main() {
let result = safe_main();
match result {
// this should not get triggered, safe_main should not return but go into deep sleep with sensbile
// this should not get triggered, safe_main should not return but go into deep sleep with sensible
// timeout, this is just a fallback
Ok(_) => {
println!("Main app finished, restarting");
@@ -849,13 +842,13 @@ fn main() {
}
pub fn in_time_range(cur: &DateTime<Tz>, start: u8, end: u8) -> bool {
let curhour = cur.hour() as u8;
let current_hour = cur.hour() as u8;
//eg 10-14
if start < end {
curhour > start && curhour < end
current_hour > start && current_hour < end
} else {
//eg 20-05
curhour > start || curhour < end
current_hour > start || current_hour < end
}
}