Compare commits
2 Commits
3fe9aaeb6f
...
b238fc4c14
Author | SHA1 | Date | |
---|---|---|---|
b238fc4c14 | |||
93b37d0991 |
@ -88,6 +88,10 @@ text-template = "0.1.0"
|
||||
strum_macros = "0.27.0"
|
||||
esp-ota = { version = "0.2.2", features = ["log"] }
|
||||
unit-enum = "1.4.1"
|
||||
ambassador = "0.4.1"
|
||||
tca9535 = "0.1.0"
|
||||
tca9539 = "0.2.1"
|
||||
pca9535 = "2.0.0"
|
||||
|
||||
|
||||
[patch.crates-io]
|
||||
|
@ -1,8 +1,4 @@
|
||||
use std::{
|
||||
fmt::Display,
|
||||
sync::{atomic::AtomicBool, Arc, Mutex},
|
||||
};
|
||||
use std::sync::MutexGuard;
|
||||
use crate::{config::PlantControllerConfig, webserver::webserver::httpd};
|
||||
use anyhow::bail;
|
||||
use chrono::{DateTime, Datelike, Timelike, Utc};
|
||||
use chrono_tz::Tz;
|
||||
@ -18,19 +14,24 @@ use esp_idf_sys::{
|
||||
use esp_ota::{mark_app_valid, rollback_and_reboot};
|
||||
use log::{log, LogMessage};
|
||||
use once_cell::sync::Lazy;
|
||||
use plant_hal::{PlantCtrlBoard, PlantHal, PLANT_COUNT};
|
||||
use plant_hal::{EspHal, PlantHalFactory, PLANT_COUNT};
|
||||
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 log;
|
||||
pub mod plant_hal;
|
||||
mod plant_state;
|
||||
mod tank;
|
||||
|
||||
use crate::plant_hal::{BoardV3X, SpecificBoard};
|
||||
use plant_state::PlantState;
|
||||
use tank::*;
|
||||
|
||||
pub static BOARD_ACCESS: Lazy<Mutex<PlantCtrlBoard>> = Lazy::new(|| PlantHal::create().unwrap());
|
||||
pub static BOARD_ACCESS: Lazy<Mutex<Box<dyn SpecificBoard + Send>>> = Lazy::new(|| PlantHalFactory::create_v3().unwrap());
|
||||
pub static STAY_ALIVE: Lazy<AtomicBool> = Lazy::new(|| AtomicBool::new(false));
|
||||
|
||||
mod webserver {
|
||||
@ -150,7 +151,7 @@ fn safe_main() -> anyhow::Result<()> {
|
||||
};
|
||||
log(LogMessage::PartitionState, 0, 0, "", ota_state_string);
|
||||
|
||||
let mut board: std::sync::MutexGuard<'_, PlantCtrlBoard<'_>> = BOARD_ACCESS.lock().unwrap();
|
||||
let mut board: std::sync::MutexGuard<'_, BoardV3X> = BOARD_ACCESS.lock().unwrap();
|
||||
board.general_fault(false);
|
||||
|
||||
log(LogMessage::MountingFilesystem, 0, 0, "", "");
|
||||
@ -484,7 +485,7 @@ fn safe_main() -> anyhow::Result<()> {
|
||||
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<EspHal<BoardV3X>>) -> anyhow::Result<f32> {
|
||||
//multisample should be moved to water_temperature_c
|
||||
let mut attempt = 1;
|
||||
let water_temp: Result<f32, anyhow::Error> = loop {
|
||||
@ -506,7 +507,7 @@ fn obtain_tank_temperature(board: &mut MutexGuard<PlantCtrlBoard>) -> anyhow::Re
|
||||
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<BoardV3X>, config: &PlantControllerConfig, tank_state: &TankState, water_temp: &anyhow::Result<f32>) {
|
||||
match serde_json::to_string(&tank_state.as_mqtt_info(&config.tank, water_temp)) {
|
||||
Ok(state) => {
|
||||
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<EspHal<BoardV3X>>, config: &PlantControllerConfig, timezone_time: &DateTime<Tz>, plantstate: &[PlantState; 8]) {
|
||||
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)) {
|
||||
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<EspHal<BoardV3X>>, 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/githash", version.git_hash.as_bytes());
|
||||
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());
|
||||
}
|
||||
|
||||
fn try_connect_wifi_sntp_mqtt(board: &mut MutexGuard<PlantCtrlBoard>, config: &PlantControllerConfig) -> NetworkMode{
|
||||
fn try_connect_wifi_sntp_mqtt(board: &mut MutexGuard<EspHal<BoardV3X>>, config: &PlantControllerConfig) -> NetworkMode{
|
||||
match board.wifi(
|
||||
config.network.ssid.clone().unwrap(),
|
||||
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
|
||||
fn pump_info(board: &mut MutexGuard<PlantCtrlBoard>, config: &PlantControllerConfig, plant_id: usize, pump_active: bool, pump_ineffective: bool) {
|
||||
fn pump_info(board: &mut MutexGuard<EspHal>, config: &PlantControllerConfig, plant_id: usize, pump_active: bool, pump_ineffective: bool) {
|
||||
let pump_info = PumpInfo {
|
||||
enabled: pump_active,
|
||||
pump_ineffective
|
||||
@ -622,7 +623,7 @@ fn pump_info(board: &mut MutexGuard<PlantCtrlBoard>, config: &PlantControllerCon
|
||||
}
|
||||
|
||||
fn publish_battery_state(
|
||||
board: &mut std::sync::MutexGuard<'_, PlantCtrlBoard<'_>>,
|
||||
board: &mut std::sync::MutexGuard<'_, EspHal<'_>>,
|
||||
config: &PlantControllerConfig,
|
||||
) {
|
||||
let bat = board.get_battery_state();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,7 @@ use chrono_tz::Tz;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{config::PlantConfig, in_time_range, plant_hal};
|
||||
use crate::plant_hal::{BoardV3X, SpecificBoard};
|
||||
|
||||
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
|
||||
@ -113,7 +114,7 @@ fn map_range_moisture(
|
||||
impl PlantState {
|
||||
pub fn read_hardware_state(
|
||||
plant_id: usize,
|
||||
board: &mut plant_hal::PlantCtrlBoard,
|
||||
board: &mut plant_hal::EspHal<BoardV3X>,
|
||||
config: &PlantConfig,
|
||||
) -> Self {
|
||||
let sensor_a = if config.sensor_a {
|
||||
|
@ -1,9 +1,7 @@
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::{
|
||||
config::{PlantControllerConfig, TankConfig},
|
||||
plant_hal::PlantCtrlBoard,
|
||||
};
|
||||
use crate::plant_hal::{EspHal, SpecificBoard};
|
||||
use crate::config::{PlantControllerConfig, TankConfig};
|
||||
|
||||
const OPEN_TANK_VOLTAGE: f32 = 3.0;
|
||||
pub const WATER_FROZEN_THRESH: f32 = 4.0;
|
||||
@ -158,7 +156,7 @@ impl TankState {
|
||||
}
|
||||
|
||||
pub fn determine_tank_state(
|
||||
board: &mut std::sync::MutexGuard<'_, PlantCtrlBoard<'_>>,
|
||||
board: &mut std::sync::MutexGuard<'_, EspHal<'_>>,
|
||||
config: &PlantControllerConfig,
|
||||
) -> TankState {
|
||||
if config.tank.tank_sensor_enabled {
|
||||
|
@ -21,6 +21,7 @@ use std::{
|
||||
use url::Url;
|
||||
|
||||
use crate::config::PlantControllerConfig;
|
||||
use crate::plant_hal::SpecificBoard;
|
||||
use crate::plant_state::MoistureSensorState;
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
@ -115,7 +116,7 @@ fn get_live_moisture(
|
||||
_request: &mut Request<&mut EspHttpConnection>,
|
||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
||||
let config = board.get_config().unwrap();
|
||||
let config = board.get_config().unwrap_or(PlantControllerConfig::default());
|
||||
|
||||
let plant_state = Vec::from_iter(
|
||||
(0..PLANT_COUNT).map(|i| PlantState::read_hardware_state(i, &mut board, &config.plants[i])),
|
||||
|
@ -279,6 +279,21 @@ export class Controller {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
selfTest() {
|
||||
controller.progressview.addIndeterminate("boardtest", "Self test running");
|
||||
|
||||
fetch(PUBLIC_URL + "/boardtest", {
|
||||
method: "POST"
|
||||
})
|
||||
.then(response => response.text())
|
||||
.then(
|
||||
_ => {
|
||||
controller.progressview.removeProgress("boardtest");
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
testPlant(plantId: number) {
|
||||
let counter = 0
|
||||
let limit = 30
|
||||
@ -466,6 +481,7 @@ export class Controller {
|
||||
controller.exit();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
const controller = new Controller();
|
||||
controller.progressview.removeProgress("rebooting");
|
||||
|
@ -5,6 +5,7 @@ export class OTAView {
|
||||
readonly firmware_buildtime: HTMLDivElement;
|
||||
readonly firmware_githash: HTMLDivElement;
|
||||
readonly firmware_partition: HTMLDivElement;
|
||||
readonly test: HTMLButtonElement;
|
||||
|
||||
constructor(controller: Controller) {
|
||||
(document.getElementById("firmwareview") as HTMLElement).innerHTML = require("./ota.html")
|
||||
@ -12,7 +13,7 @@ export class OTAView {
|
||||
this.firmware_buildtime = document.getElementById("firmware_buildtime") as HTMLDivElement;
|
||||
this.firmware_githash = document.getElementById("firmware_githash") as HTMLDivElement;
|
||||
this.firmware_partition = document.getElementById("firmware_partition") as HTMLDivElement;
|
||||
|
||||
this.test = document.getElementById("test") as HTMLButtonElement;
|
||||
|
||||
const file = document.getElementById("firmware_file") as HTMLInputElement;
|
||||
this.file1Upload = file
|
||||
@ -24,6 +25,10 @@ export class OTAView {
|
||||
}
|
||||
controller.uploadNewFirmware(selectedFile);
|
||||
};
|
||||
|
||||
this.test.onclick = () => {
|
||||
controller.selfTest()
|
||||
}
|
||||
}
|
||||
|
||||
setVersion(versionInfo: VersionInfo) {
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 26d1205439b460bee960fd4c29f3c5c20948875f
|
||||
Subproject commit 1d21656d5efcf6a6b247245d057bf553f3209f39
|
Loading…
x
Reference in New Issue
Block a user