Part 1 of V3 extraction in preperation of v4 and v3 software merge
This commit is contained in:
parent
3fe9aaeb6f
commit
38f4ada433
@ -1,8 +1,4 @@
|
|||||||
use std::{
|
use crate::{config::PlantControllerConfig, webserver::webserver::httpd};
|
||||||
fmt::Display,
|
|
||||||
sync::{atomic::AtomicBool, Arc, Mutex},
|
|
||||||
};
|
|
||||||
use std::sync::MutexGuard;
|
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use chrono::{DateTime, Datelike, Timelike, Utc};
|
use chrono::{DateTime, Datelike, Timelike, Utc};
|
||||||
use chrono_tz::Tz;
|
use chrono_tz::Tz;
|
||||||
@ -18,19 +14,24 @@ use esp_idf_sys::{
|
|||||||
use esp_ota::{mark_app_valid, rollback_and_reboot};
|
use esp_ota::{mark_app_valid, rollback_and_reboot};
|
||||||
use log::{log, LogMessage};
|
use log::{log, LogMessage};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use plant_hal::{PlantCtrlBoard, PlantHal, PLANT_COUNT};
|
use plant_hal::{PlantHal, PLANT_COUNT};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use crate::{config::PlantControllerConfig, webserver::webserver::httpd};
|
use std::sync::MutexGuard;
|
||||||
|
use std::{
|
||||||
|
fmt::Display,
|
||||||
|
sync::{atomic::AtomicBool, Arc, Mutex},
|
||||||
|
};
|
||||||
mod config;
|
mod config;
|
||||||
mod log;
|
mod log;
|
||||||
pub mod plant_hal;
|
pub mod plant_hal;
|
||||||
mod plant_state;
|
mod plant_state;
|
||||||
mod tank;
|
mod tank;
|
||||||
|
|
||||||
|
use crate::plant_hal::{BatteryInteraction, BoardInteraction, HAL};
|
||||||
use plant_state::PlantState;
|
use plant_state::PlantState;
|
||||||
use tank::*;
|
use tank::*;
|
||||||
|
|
||||||
pub static BOARD_ACCESS: Lazy<Mutex<PlantCtrlBoard>> = Lazy::new(|| PlantHal::create().unwrap());
|
pub static BOARD_ACCESS: Lazy<Mutex<HAL>> = Lazy::new(|| PlantHal::create_v3().unwrap());
|
||||||
pub static STAY_ALIVE: Lazy<AtomicBool> = Lazy::new(|| AtomicBool::new(false));
|
pub static STAY_ALIVE: Lazy<AtomicBool> = Lazy::new(|| AtomicBool::new(false));
|
||||||
|
|
||||||
mod webserver {
|
mod webserver {
|
||||||
@ -150,7 +151,7 @@ fn safe_main() -> anyhow::Result<()> {
|
|||||||
};
|
};
|
||||||
log(LogMessage::PartitionState, 0, 0, "", ota_state_string);
|
log(LogMessage::PartitionState, 0, 0, "", ota_state_string);
|
||||||
|
|
||||||
let mut board: std::sync::MutexGuard<'_, PlantCtrlBoard<'_>> = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().unwrap();
|
||||||
board.general_fault(false);
|
board.general_fault(false);
|
||||||
|
|
||||||
log(LogMessage::MountingFilesystem, 0, 0, "", "");
|
log(LogMessage::MountingFilesystem, 0, 0, "", "");
|
||||||
@ -400,7 +401,7 @@ fn safe_main() -> anyhow::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let is_day = board.is_day();
|
let is_day = board.is_day();
|
||||||
let state_of_charge = board.state_charge_percent().unwrap_or(0);
|
let state_of_charge = board.battery_monitor.state_charge_percent().unwrap_or(0);
|
||||||
|
|
||||||
let mut light_state = LightState {
|
let mut light_state = LightState {
|
||||||
enabled: config.night_lamp.enabled,
|
enabled: config.night_lamp.enabled,
|
||||||
@ -484,7 +485,7 @@ fn safe_main() -> anyhow::Result<()> {
|
|||||||
board.deep_sleep(1000 * 1000 * 60 * deep_sleep_duration_minutes as u64);
|
board.deep_sleep(1000 * 1000 * 60 * deep_sleep_duration_minutes as u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn obtain_tank_temperature(board: &mut MutexGuard<PlantCtrlBoard>) -> anyhow::Result<f32> {
|
fn obtain_tank_temperature(board: &mut MutexGuard<HAL>) -> anyhow::Result<f32> {
|
||||||
//multisample should be moved to water_temperature_c
|
//multisample should be moved to water_temperature_c
|
||||||
let mut attempt = 1;
|
let mut attempt = 1;
|
||||||
let water_temp: Result<f32, anyhow::Error> = loop {
|
let water_temp: Result<f32, anyhow::Error> = loop {
|
||||||
@ -506,7 +507,7 @@ fn obtain_tank_temperature(board: &mut MutexGuard<PlantCtrlBoard>) -> anyhow::Re
|
|||||||
water_temp
|
water_temp
|
||||||
}
|
}
|
||||||
|
|
||||||
fn publish_tank_state(board: &mut MutexGuard<PlantCtrlBoard>, config: &PlantControllerConfig, tank_state: &TankState, water_temp: &anyhow::Result<f32>) {
|
fn publish_tank_state(board: &mut MutexGuard<HAL>, config: &PlantControllerConfig, tank_state: &TankState, water_temp: &anyhow::Result<f32>) {
|
||||||
match serde_json::to_string(&tank_state.as_mqtt_info(&config.tank, water_temp)) {
|
match serde_json::to_string(&tank_state.as_mqtt_info(&config.tank, water_temp)) {
|
||||||
Ok(state) => {
|
Ok(state) => {
|
||||||
let _ = board.mqtt_publish(&config, "/water", state.as_bytes());
|
let _ = board.mqtt_publish(&config, "/water", state.as_bytes());
|
||||||
@ -517,7 +518,7 @@ fn publish_tank_state(board: &mut MutexGuard<PlantCtrlBoard>, config: &PlantCont
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn publish_plant_states(board: &mut MutexGuard<PlantCtrlBoard>, config: &PlantControllerConfig, timezone_time: &DateTime<Tz>, plantstate: &[PlantState; 8]) {
|
fn publish_plant_states(board: &mut MutexGuard<HAL>, config: &PlantControllerConfig, timezone_time: &DateTime<Tz>, plantstate: &[PlantState; 8]) {
|
||||||
for (plant_id, (plant_state, plant_conf)) in plantstate.iter().zip(&config.plants).enumerate() {
|
for (plant_id, (plant_state, plant_conf)) in plantstate.iter().zip(&config.plants).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) => {
|
Ok(state) => {
|
||||||
@ -533,7 +534,7 @@ fn publish_plant_states(board: &mut MutexGuard<PlantCtrlBoard>, config: &PlantCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn publish_firmware_info(version: VersionInfo, address: u32, ota_state_string: &str, board: &mut MutexGuard<PlantCtrlBoard>, config: &PlantControllerConfig, ip_address: &String, timezone_time: DateTime<Tz>) {
|
fn publish_firmware_info(version: VersionInfo, address: u32, ota_state_string: &str, board: &mut MutexGuard<HAL>, config: &PlantControllerConfig, ip_address: &String, timezone_time: DateTime<Tz>) {
|
||||||
let _ = board.mqtt_publish(&config, "/firmware/address", ip_address.as_bytes());
|
let _ = board.mqtt_publish(&config, "/firmware/address", ip_address.as_bytes());
|
||||||
let _ = board.mqtt_publish(&config, "/firmware/githash", version.git_hash.as_bytes());
|
let _ = board.mqtt_publish(&config, "/firmware/githash", version.git_hash.as_bytes());
|
||||||
let _ = board.mqtt_publish(
|
let _ = board.mqtt_publish(
|
||||||
@ -555,7 +556,7 @@ fn publish_firmware_info(version: VersionInfo, address: u32, ota_state_string: &
|
|||||||
let _ = board.mqtt_publish(&config, "/state", "online".as_bytes());
|
let _ = board.mqtt_publish(&config, "/state", "online".as_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_connect_wifi_sntp_mqtt(board: &mut MutexGuard<PlantCtrlBoard>, config: &PlantControllerConfig) -> NetworkMode{
|
fn try_connect_wifi_sntp_mqtt(board: &mut MutexGuard<HAL>, config: &PlantControllerConfig) -> NetworkMode{
|
||||||
match board.wifi(
|
match board.wifi(
|
||||||
config.network.ssid.clone().unwrap(),
|
config.network.ssid.clone().unwrap(),
|
||||||
config.network.password.clone(),
|
config.network.password.clone(),
|
||||||
@ -603,7 +604,7 @@ fn try_connect_wifi_sntp_mqtt(board: &mut MutexGuard<PlantCtrlBoard>, config: &P
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO clean this up? better state
|
//TODO clean this up? better state
|
||||||
fn pump_info(board: &mut MutexGuard<PlantCtrlBoard>, config: &PlantControllerConfig, plant_id: usize, pump_active: bool, pump_ineffective: bool) {
|
fn pump_info(board: &mut MutexGuard<HAL>, config: &PlantControllerConfig, plant_id: usize, pump_active: bool, pump_ineffective: bool) {
|
||||||
let pump_info = PumpInfo {
|
let pump_info = PumpInfo {
|
||||||
enabled: pump_active,
|
enabled: pump_active,
|
||||||
pump_ineffective
|
pump_ineffective
|
||||||
@ -622,19 +623,12 @@ fn pump_info(board: &mut MutexGuard<PlantCtrlBoard>, config: &PlantControllerCon
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn publish_battery_state(
|
fn publish_battery_state(
|
||||||
board: &mut std::sync::MutexGuard<'_, PlantCtrlBoard<'_>>,
|
board: &mut MutexGuard<'_, HAL<'_>>,
|
||||||
config: &PlantControllerConfig,
|
config: &PlantControllerConfig,
|
||||||
) {
|
) {
|
||||||
let bat = board.get_battery_state();
|
let state = board.get_battery_state();
|
||||||
match serde_json::to_string(&bat) {
|
|
||||||
Ok(state) => {
|
|
||||||
let _ = board.mqtt_publish(config, "/battery", state.as_bytes());
|
let _ = board.mqtt_publish(config, "/battery", state.as_bytes());
|
||||||
}
|
}
|
||||||
Err(err) => {
|
|
||||||
println!("Error publishing battery_state {}", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn wait_infinity(wait_type: WaitType, reboot_now: Arc<AtomicBool>) -> ! {
|
fn wait_infinity(wait_type: WaitType, reboot_now: Arc<AtomicBool>) -> ! {
|
||||||
let delay = wait_type.blink_pattern();
|
let delay = wait_type.blink_pattern();
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@ use chrono_tz::Tz;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{config::PlantConfig, in_time_range, plant_hal};
|
use crate::{config::PlantConfig, in_time_range, plant_hal};
|
||||||
|
use crate::plant_hal::BoardInteraction;
|
||||||
|
|
||||||
const MOIST_SENSOR_MAX_FREQUENCY: f32 = 7500.; // 60kHz (500Hz margin)
|
const MOIST_SENSOR_MAX_FREQUENCY: f32 = 7500.; // 60kHz (500Hz margin)
|
||||||
const MOIST_SENSOR_MIN_FREQUENCY: f32 = 150.; // this is really, really dry, think like cactus levels
|
const MOIST_SENSOR_MIN_FREQUENCY: f32 = 150.; // this is really, really dry, think like cactus levels
|
||||||
@ -113,7 +114,7 @@ fn map_range_moisture(
|
|||||||
impl PlantState {
|
impl PlantState {
|
||||||
pub fn read_hardware_state(
|
pub fn read_hardware_state(
|
||||||
plant_id: usize,
|
plant_id: usize,
|
||||||
board: &mut plant_hal::PlantCtrlBoard,
|
board: &mut plant_hal::HAL,
|
||||||
config: &PlantConfig,
|
config: &PlantConfig,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let sensor_a = if config.sensor_a {
|
let sensor_a = if config.sensor_a {
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::plant_hal::{BoardInteraction, HAL};
|
||||||
config::{PlantControllerConfig, TankConfig},
|
use crate::config::{PlantControllerConfig, TankConfig};
|
||||||
plant_hal::PlantCtrlBoard,
|
|
||||||
};
|
|
||||||
|
|
||||||
const OPEN_TANK_VOLTAGE: f32 = 3.0;
|
const OPEN_TANK_VOLTAGE: f32 = 3.0;
|
||||||
pub const WATER_FROZEN_THRESH: f32 = 4.0;
|
pub const WATER_FROZEN_THRESH: f32 = 4.0;
|
||||||
@ -158,7 +156,7 @@ impl TankState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn determine_tank_state(
|
pub fn determine_tank_state(
|
||||||
board: &mut std::sync::MutexGuard<'_, PlantCtrlBoard<'_>>,
|
board: &mut std::sync::MutexGuard<'_, HAL<'_>>,
|
||||||
config: &PlantControllerConfig,
|
config: &PlantControllerConfig,
|
||||||
) -> TankState {
|
) -> TankState {
|
||||||
if config.tank.tank_sensor_enabled {
|
if config.tank.tank_sensor_enabled {
|
||||||
|
@ -8,7 +8,6 @@ use anyhow::bail;
|
|||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use core::result::Result::Ok;
|
use core::result::Result::Ok;
|
||||||
use embedded_svc::http::Method;
|
use embedded_svc::http::Method;
|
||||||
use esp_idf_hal::delay::Delay;
|
|
||||||
use esp_idf_svc::http::server::{Configuration, EspHttpConnection, EspHttpServer, Request};
|
use esp_idf_svc::http::server::{Configuration, EspHttpConnection, EspHttpServer, Request};
|
||||||
use esp_idf_sys::{settimeofday, timeval, vTaskDelay};
|
use esp_idf_sys::{settimeofday, timeval, vTaskDelay};
|
||||||
use esp_ota::OtaUpdate;
|
use esp_ota::OtaUpdate;
|
||||||
@ -21,6 +20,7 @@ use std::{
|
|||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::config::PlantControllerConfig;
|
use crate::config::PlantControllerConfig;
|
||||||
|
use crate::plant_hal::BoardInteraction;
|
||||||
use crate::plant_state::MoistureSensorState;
|
use crate::plant_state::MoistureSensorState;
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
@ -351,45 +351,6 @@ fn ota(
|
|||||||
anyhow::Ok(None)
|
anyhow::Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flash_bq(filename: &str, dryrun: bool) -> anyhow::Result<()> {
|
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
|
||||||
|
|
||||||
let mut toggle = true;
|
|
||||||
let delay = Delay::new(1);
|
|
||||||
|
|
||||||
let file_handle = board.get_file_handle(filename, false)?;
|
|
||||||
|
|
||||||
let mut reader = std::io::BufRead::lines(std::io::BufReader::with_capacity(512, file_handle));
|
|
||||||
let mut line = 0;
|
|
||||||
loop {
|
|
||||||
board.general_fault(toggle);
|
|
||||||
toggle = !toggle;
|
|
||||||
|
|
||||||
delay.delay_us(2);
|
|
||||||
line += 1;
|
|
||||||
match reader.next() {
|
|
||||||
Some(next) => {
|
|
||||||
let input = next?;
|
|
||||||
println!("flashing bq34z100 dryrun:{dryrun} line {line} payload: {input}");
|
|
||||||
match board.flash_bq34_z100(&input, dryrun) {
|
|
||||||
Ok(_) => {
|
|
||||||
println!("ok")
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
bail!(
|
|
||||||
"Error flashing bq34z100 in dryrun: {dryrun} line: {line} error: {err}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("Finished flashing file {line} lines processed");
|
|
||||||
board.general_fault(false);
|
|
||||||
anyhow::Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn query_param(uri: &str, param_name: &str) -> Option<std::string::String> {
|
fn query_param(uri: &str, param_name: &str) -> Option<std::string::String> {
|
||||||
println!("{uri} get {param_name}");
|
println!("{uri} get {param_name}");
|
||||||
let parsed = Url::parse(&format!("http://127.0.0.1/{uri}")).unwrap();
|
let parsed = Url::parse(&format!("http://127.0.0.1/{uri}")).unwrap();
|
||||||
@ -630,35 +591,6 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
cors_response(request, 200, "")
|
cors_response(request, 200, "")
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
server
|
|
||||||
.fn_handler("/flashbattery", Method::Post, move |request| {
|
|
||||||
let filename = query_param(request.uri(),"filename").unwrap();
|
|
||||||
let dryrun = true;
|
|
||||||
match flash_bq(&filename, false) {
|
|
||||||
Ok(_) => {
|
|
||||||
if !dryrun {
|
|
||||||
match flash_bq(&filename, true) {
|
|
||||||
Ok(_) => {
|
|
||||||
cors_response(request, 200, "Sucessfully flashed bq34z100")?;
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
let info = format!("Could not flash bq34z100, could be bricked now! {filename} {err:?}");
|
|
||||||
cors_response(request, 500, &info)?;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cors_response(request, 200, "Sucessfully processed bq34z100")?;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
let info = format!("Could not process firmware file for, bq34z100, refusing to flash! {filename} {err:?}");
|
|
||||||
cors_response(request, 500, &info)?;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
anyhow::Ok(())
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
unsafe { vTaskDelay(1) };
|
unsafe { vTaskDelay(1) };
|
||||||
server
|
server
|
||||||
.fn_handler("/", Method::Get, move |request| {
|
.fn_handler("/", Method::Get, move |request| {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user