wifi config file handling added
This commit is contained in:
		@@ -74,6 +74,7 @@ one-wire-bus = "0.1.1"
 | 
				
			|||||||
anyhow = { version = "1.0.75", features = ["std", "backtrace"] }
 | 
					anyhow = { version = "1.0.75", features = ["std", "backtrace"] }
 | 
				
			||||||
schemars = "0.8.16"
 | 
					schemars = "0.8.16"
 | 
				
			||||||
heapless = { version = "0.8.0", features = ["serde"] }
 | 
					heapless = { version = "0.8.0", features = ["serde"] }
 | 
				
			||||||
 | 
					serde_json = "1.0.108"
 | 
				
			||||||
#?bq34z100 required
 | 
					#?bq34z100 required
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[build-dependencies]
 | 
					[build-dependencies]
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,12 @@
 | 
				
			|||||||
 | 
					use std::fmt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use serde::{Serialize, Deserialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::PLANT_COUNT;
 | 
					use crate::PLANT_COUNT;
 | 
				
			||||||
pub struct Config {
 | 
					 | 
				
			||||||
    ssid: heapless::String<32>,
 | 
					 | 
				
			||||||
    password: Option<heapless::String<64>>,
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub struct Config {
 | 
				
			||||||
    tank_sensor_enabled: bool,
 | 
					    tank_sensor_enabled: bool,
 | 
				
			||||||
    tank_full_ml: u32,
 | 
					    tank_full_ml: u32,
 | 
				
			||||||
    tank_warn_percent: u8,
 | 
					    tank_warn_percent: u8,
 | 
				
			||||||
@@ -19,6 +21,16 @@ pub struct Config {
 | 
				
			|||||||
    night_lamp_hour_start: u8,
 | 
					    night_lamp_hour_start: u8,
 | 
				
			||||||
    night_lamp_hour_end: u8,
 | 
					    night_lamp_hour_end: u8,
 | 
				
			||||||
    night_lamp_only_when_dark: u8
 | 
					    night_lamp_only_when_dark: u8
 | 
				
			||||||
    
 | 
					}
 | 
				
			||||||
    
 | 
					#[derive(Serialize, Deserialize)]
 | 
				
			||||||
 | 
					#[derive(Debug)]
 | 
				
			||||||
 | 
					pub struct WifiConfig {
 | 
				
			||||||
 | 
					    pub ssid: heapless::String<32>,
 | 
				
			||||||
 | 
					    pub password: Option<heapless::String<64>>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl fmt::Display for WifiConfig {
 | 
				
			||||||
 | 
					    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 | 
				
			||||||
 | 
					        write!(f, "({}, ****)", self.ssid)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
							
								
								
									
										166
									
								
								rust/src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										166
									
								
								rust/src/main.rs
									
									
									
									
									
								
							@@ -2,6 +2,7 @@ use std::{
 | 
				
			|||||||
    ffi::CString,
 | 
					    ffi::CString,
 | 
				
			||||||
    fs::File,
 | 
					    fs::File,
 | 
				
			||||||
    io::{Read, Write},
 | 
					    io::{Read, Write},
 | 
				
			||||||
 | 
					    mem,
 | 
				
			||||||
    str::from_utf8,
 | 
					    str::from_utf8,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -11,14 +12,39 @@ use anyhow::{Context, Result};
 | 
				
			|||||||
use chrono_tz::Europe::Berlin;
 | 
					use chrono_tz::Europe::Berlin;
 | 
				
			||||||
use esp_idf_hal::delay::Delay;
 | 
					use esp_idf_hal::delay::Delay;
 | 
				
			||||||
use esp_idf_svc::http::server::EspHttpServer;
 | 
					use esp_idf_svc::http::server::EspHttpServer;
 | 
				
			||||||
use plant_hal::{CreatePlantHal, PlantCtrlBoardInteraction, PlantHal, PLANT_COUNT};
 | 
					use esp_idf_sys::{esp_restart, vTaskDelay, TickType_t};
 | 
				
			||||||
 | 
					use heapless::String;
 | 
				
			||||||
 | 
					use plant_hal::{CreatePlantHal, PlantCtrlBoard, PlantCtrlBoardInteraction, PlantHal, PLANT_COUNT};
 | 
				
			||||||
use webserver::webserver::httpd;
 | 
					use webserver::webserver::httpd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use crate::config::{Config, WifiConfig};
 | 
				
			||||||
mod config;
 | 
					mod config;
 | 
				
			||||||
pub mod plant_hal;
 | 
					pub mod plant_hal;
 | 
				
			||||||
mod webserver {
 | 
					mod webserver {
 | 
				
			||||||
    pub mod webserver;
 | 
					    pub mod webserver;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(PartialEq)]
 | 
				
			||||||
 | 
					enum OnlineMode {
 | 
				
			||||||
 | 
					    Offline,
 | 
				
			||||||
 | 
					    Wifi,
 | 
				
			||||||
 | 
					    SnTp,
 | 
				
			||||||
 | 
					    Mqtt,
 | 
				
			||||||
 | 
					    MqttRoundtrip
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn wait_infinity(board: &mut PlantCtrlBoard<'_>) {
 | 
				
			||||||
 | 
					    loop {
 | 
				
			||||||
 | 
					        unsafe {
 | 
				
			||||||
 | 
					            //do not trigger watchdog
 | 
				
			||||||
 | 
					            board.general_fault(true);
 | 
				
			||||||
 | 
					            vTaskDelay(500_u32);
 | 
				
			||||||
 | 
					            board.general_fault(false);
 | 
				
			||||||
 | 
					            vTaskDelay(500_u32);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() -> Result<()> {
 | 
					fn main() -> Result<()> {
 | 
				
			||||||
    // It is necessary to call this function once. Otherwise some patches to the runtime
 | 
					    // It is necessary to call this function once. Otherwise some patches to the runtime
 | 
				
			||||||
    // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
 | 
					    // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71
 | 
				
			||||||
@@ -32,10 +58,15 @@ fn main() -> Result<()> {
 | 
				
			|||||||
    let git_hash = env!("VERGEN_GIT_DESCRIBE");
 | 
					    let git_hash = env!("VERGEN_GIT_DESCRIBE");
 | 
				
			||||||
    println!("Version useing git has {}", git_hash);
 | 
					    println!("Version useing git has {}", git_hash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
        let mut board = PlantHal::create()?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    println!("Board hal init");
 | 
					    println!("Board hal init");
 | 
				
			||||||
 | 
					    let mut board = PlantHal::create()?;
 | 
				
			||||||
 | 
					    println!("Mounting filesystem");
 | 
				
			||||||
 | 
					    board.mountFileSystem()?;
 | 
				
			||||||
 | 
					    let free_space = board.fileSystemSize()?;
 | 
				
			||||||
 | 
					    println!(
 | 
				
			||||||
 | 
					        "Mounted, total space {} used {} free {}",
 | 
				
			||||||
 | 
					        free_space.total_size, free_space.used_size, free_space.free_size
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let time = board.time();
 | 
					    let time = board.time();
 | 
				
			||||||
    let mut cur = match time {
 | 
					    let mut cur = match time {
 | 
				
			||||||
@@ -57,22 +88,45 @@ fn main() -> Result<()> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    println!("cur is {}", cur);
 | 
					    println!("cur is {}", cur);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if board.is_config_reset() {
 | 
				
			||||||
 | 
					        println!("Reset config is pressed, waiting 5s");
 | 
				
			||||||
 | 
					        Delay::new_default().delay_ms(5000);
 | 
				
			||||||
 | 
					        if board.is_config_reset() {
 | 
				
			||||||
 | 
					            println!("Reset config is still pressed, deleting configs and reboot");
 | 
				
			||||||
 | 
					            match board.remove_configs() {
 | 
				
			||||||
 | 
					                Ok(_) => {
 | 
				
			||||||
 | 
					                    println!("Removed config files, restarting");
 | 
				
			||||||
 | 
					                    unsafe {
 | 
				
			||||||
 | 
					                        esp_restart();
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                Err(err) => {
 | 
				
			||||||
 | 
					                    println!("Could not remove config files, system borked {}", err);
 | 
				
			||||||
 | 
					                    //terminate main app and freeze
 | 
				
			||||||
 | 
					                    wait_infinity(&mut board);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let mut online_mode = OnlineMode::Offline;
 | 
				
			||||||
 | 
					    let wifi_conf = board.get_wifi();
 | 
				
			||||||
        //continous/interrupt?
 | 
					    let wifi: WifiConfig;
 | 
				
			||||||
            //check if boot button is pressed, if longer than 5s delete config and reboot into config mode
 | 
					    match wifi_conf{
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let config = board.get_config();
 | 
					 | 
				
			||||||
        match config {
 | 
					 | 
				
			||||||
        Ok(conf) => {
 | 
					        Ok(conf) => {
 | 
				
			||||||
 | 
					            wifi = conf;
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        Err(err) => {
 | 
					        Err(err) => {
 | 
				
			||||||
 | 
					            println!("Missing wifi config, entering initial config mode {}", err);
 | 
				
			||||||
 | 
					            //config upload will trigger reboot!
 | 
				
			||||||
 | 
					            let _webserver = httpd(true);
 | 
				
			||||||
 | 
					            wait_infinity(&mut board);
 | 
				
			||||||
 | 
					            //how to do this better?
 | 
				
			||||||
 | 
					            let ssid: String<32> = String::try_from("").unwrap();
 | 
				
			||||||
 | 
					            wifi = WifiConfig { ssid : ssid, password : None};
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        }
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //    let proceed = config.unwrap();
 | 
					    //    let proceed = config.unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -94,74 +148,63 @@ fn main() -> Result<()> {
 | 
				
			|||||||
    match tank_value {
 | 
					    match tank_value {
 | 
				
			||||||
        Ok(tank_raw) => {
 | 
					        Ok(tank_raw) => {
 | 
				
			||||||
            println!("Tank sensor returned {}", tank_raw);
 | 
					            println!("Tank sensor returned {}", tank_raw);
 | 
				
			||||||
                },
 | 
					        }
 | 
				
			||||||
        Err(_) => {
 | 
					        Err(_) => {
 | 
				
			||||||
            //if not possible value, blink general fault error_tank_sensor_fault
 | 
					            //if not possible value, blink general fault error_tank_sensor_fault
 | 
				
			||||||
            board.general_fault(true);
 | 
					            board.general_fault(true);
 | 
				
			||||||
            //set general fault persistent
 | 
					            //set general fault persistent
 | 
				
			||||||
            //set tank sensor state to fault
 | 
					            //set tank sensor state to fault
 | 
				
			||||||
                },
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    //measure each plant moisture
 | 
					    //measure each plant moisture
 | 
				
			||||||
        let mut initial_measurements_a: [i32;PLANT_COUNT] = [0;PLANT_COUNT];
 | 
					    let mut initial_measurements_a: [i32; PLANT_COUNT] = [0; PLANT_COUNT];
 | 
				
			||||||
        let mut initial_measurements_b: [i32;PLANT_COUNT] = [0;PLANT_COUNT];
 | 
					    let mut initial_measurements_b: [i32; PLANT_COUNT] = [0; PLANT_COUNT];
 | 
				
			||||||
        let mut initial_measurements_p: [i32;PLANT_COUNT] = [0;PLANT_COUNT];
 | 
					    let mut initial_measurements_p: [i32; PLANT_COUNT] = [0; PLANT_COUNT];
 | 
				
			||||||
    for plant in 0..PLANT_COUNT {
 | 
					    for plant in 0..PLANT_COUNT {
 | 
				
			||||||
        initial_measurements_a[plant] = board.measure_moisture_hz(plant, plant_hal::Sensor::A)?;
 | 
					        initial_measurements_a[plant] = board.measure_moisture_hz(plant, plant_hal::Sensor::A)?;
 | 
				
			||||||
        initial_measurements_b[plant] = board.measure_moisture_hz(plant, plant_hal::Sensor::B)?;
 | 
					        initial_measurements_b[plant] = board.measure_moisture_hz(plant, plant_hal::Sensor::B)?;
 | 
				
			||||||
            initial_measurements_p[plant] = board.measure_moisture_hz(plant, plant_hal::Sensor::PUMP)?;
 | 
					        initial_measurements_p[plant] =
 | 
				
			||||||
 | 
					            board.measure_moisture_hz(plant, plant_hal::Sensor::PUMP)?;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //match board.wifi("C3MA", Some("chaosimquadrat"), 10000) {
 | 
					    println!("attempting to connect wifi");
 | 
				
			||||||
        //    Ok(_) => println!("online mode"),
 | 
					    match board.wifi(&wifi.ssid, wifi.password.as_deref(), 10000) {
 | 
				
			||||||
        //    Err(_) => {
 | 
					        Ok(_) => {
 | 
				
			||||||
 | 
					            online_mode = OnlineMode::Wifi;
 | 
				
			||||||
    //            println!("Offline mode");
 | 
					        }
 | 
				
			||||||
            //},
 | 
					        Err(_) => {
 | 
				
			||||||
        //}
 | 
					            println!("Offline mode");
 | 
				
			||||||
        //try connect wifi and do mqtt roundtrip
 | 
					            board.general_fault(true);
 | 
				
			||||||
            // if no wifi, set general fault persistent
 | 
					        }
 | 
				
			||||||
                //if no mqtt, set general fault persistent
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let mut total_size = 0;
 | 
					 | 
				
			||||||
    let mut used_size = 0;         
 | 
					 | 
				
			||||||
    unsafe {
 | 
					 | 
				
			||||||
        let base_path = CString::new("/spiffs")?;
 | 
					 | 
				
			||||||
        let storage = CString::new("storage")?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let conf = esp_idf_sys::esp_vfs_spiffs_conf_t {
 | 
					 | 
				
			||||||
            base_path: base_path.as_ptr(),
 | 
					 | 
				
			||||||
            partition_label: storage.as_ptr(),
 | 
					 | 
				
			||||||
            max_files: 5,
 | 
					 | 
				
			||||||
            format_if_mount_failed: true,
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        esp_idf_sys::esp!(esp_idf_sys::esp_vfs_spiffs_register(&conf))?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        esp_idf_sys::esp!(esp_idf_sys::esp_spiffs_info(storage.as_ptr(),&mut total_size,&mut used_size))?;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    println!("Total spiffs size is {}, used size is {}", total_size, used_size);
 | 
					 | 
				
			||||||
    println!("writing");
 | 
					 | 
				
			||||||
    let mut config_file = File::create("/spiffs/config.cfg")?;
 | 
					 | 
				
			||||||
    config_file.write_all("test stuff".as_bytes())?;
 | 
					 | 
				
			||||||
    config_file.flush()?;
 | 
					 | 
				
			||||||
    println!("Reading");
 | 
					 | 
				
			||||||
    let mut cfg = File::open("/spiffs/config.cfg")?;
 | 
					 | 
				
			||||||
    let mut data: [u8; 512] = [0; 512];
 | 
					 | 
				
			||||||
    let read = cfg.read(&mut data)?;
 | 
					 | 
				
			||||||
    println!("Read file {}", from_utf8(&data[0..read])?);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* 
 | 
					    if online_mode == OnlineMode::Wifi {
 | 
				
			||||||
        match board.sntp(1000 * 120) {
 | 
					        match board.sntp(1000 * 120) {
 | 
				
			||||||
        Ok(new_time) => cur = new_time,
 | 
					            Ok(new_time) => {
 | 
				
			||||||
 | 
					                cur = new_time;
 | 
				
			||||||
 | 
					                online_mode = OnlineMode::SnTp;
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
            Err(err) => {
 | 
					            Err(err) => {
 | 
				
			||||||
                println!("sntp error: {}", err);
 | 
					                println!("sntp error: {}", err);
 | 
				
			||||||
 | 
					                board.general_fault(true);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        println!("Running logic at utc {}", cur);
 | 
					        println!("Running logic at utc {}", cur);
 | 
				
			||||||
        let europe_time = cur.with_timezone(&Berlin);
 | 
					        let europe_time = cur.with_timezone(&Berlin);
 | 
				
			||||||
        println!("Running logic at europe/berlin {}", europe_time);
 | 
					        println!("Running logic at europe/berlin {}", europe_time);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(online_mode == OnlineMode::SnTp){
 | 
				
			||||||
 | 
					        //mqtt here
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if(online_mode == OnlineMode::Mqtt){
 | 
				
			||||||
 | 
					        //mqtt roundtrip here
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    //TODO configmode webserver logic here
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        //if config battery mode
 | 
					        //if config battery mode
 | 
				
			||||||
        //read battery level
 | 
					        //read battery level
 | 
				
			||||||
@@ -209,7 +252,8 @@ fn main() -> Result<()> {
 | 
				
			|||||||
            //let freertos do shit
 | 
					            //let freertos do shit
 | 
				
			||||||
            delay.delay_ms(1001);
 | 
					            delay.delay_ms(1001);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
*/
 | 
					    */
 | 
				
			||||||
 | 
					    //deepsleep here?
 | 
				
			||||||
    return Ok(());
 | 
					    return Ok(());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,12 +1,15 @@
 | 
				
			|||||||
//mod config;
 | 
					//mod config;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use embedded_svc::wifi::{Configuration, ClientConfiguration, AuthMethod};
 | 
					use embedded_svc::wifi::{Configuration, ClientConfiguration, AuthMethod, Wifi};
 | 
				
			||||||
use esp_idf_svc::eventloop::EspSystemEventLoop;
 | 
					use esp_idf_svc::eventloop::EspSystemEventLoop;
 | 
				
			||||||
use esp_idf_svc::nvs::EspDefaultNvsPartition;
 | 
					use esp_idf_svc::nvs::EspDefaultNvsPartition;
 | 
				
			||||||
use esp_idf_svc::wifi::EspWifi;
 | 
					use esp_idf_svc::wifi::EspWifi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use std::ffi::CString;
 | 
				
			||||||
use std::fs::File;
 | 
					use std::fs::File;
 | 
				
			||||||
use std::io::Read;
 | 
					use std::io::{Read, BufReader};
 | 
				
			||||||
 | 
					use std::path::Path;
 | 
				
			||||||
 | 
					use std::str::from_utf8;
 | 
				
			||||||
use std::sync::Mutex;
 | 
					use std::sync::Mutex;
 | 
				
			||||||
use anyhow::{Context, Result, bail, Ok};
 | 
					use anyhow::{Context, Result, bail, Ok};
 | 
				
			||||||
use anyhow::anyhow;
 | 
					use anyhow::anyhow;
 | 
				
			||||||
@@ -25,10 +28,11 @@ use esp_idf_svc::systime::EspSystemTime;
 | 
				
			|||||||
use esp_idf_sys::EspError;
 | 
					use esp_idf_sys::EspError;
 | 
				
			||||||
use one_wire_bus::OneWire;
 | 
					use one_wire_bus::OneWire;
 | 
				
			||||||
use shift_register_driver::sipo::ShiftRegister40;
 | 
					use shift_register_driver::sipo::ShiftRegister40;
 | 
				
			||||||
use esp_idf_hal::gpio::{PinDriver, Gpio39, Gpio4, AnyInputPin};
 | 
					use esp_idf_hal::gpio::{PinDriver, Gpio39, Gpio4, AnyInputPin, Level};
 | 
				
			||||||
use esp_idf_hal::prelude::Peripherals;
 | 
					use esp_idf_hal::prelude::Peripherals;
 | 
				
			||||||
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::config;
 | 
					use crate::config::{self, WifiConfig};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub const PLANT_COUNT:usize = 8;
 | 
					pub const PLANT_COUNT:usize = 8;
 | 
				
			||||||
const PINS_PER_PLANT:usize = 5;
 | 
					const PINS_PER_PLANT:usize = 5;
 | 
				
			||||||
@@ -38,6 +42,9 @@ const PLANT_MOIST_PUMP_OFFSET:usize = 2;
 | 
				
			|||||||
const PLANT_MOIST_B_OFFSET:usize = 3;
 | 
					const PLANT_MOIST_B_OFFSET:usize = 3;
 | 
				
			||||||
const PLANT_MOIST_A_OFFSET:usize = 4;
 | 
					const PLANT_MOIST_A_OFFSET:usize = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const SPIFFS_PARTITION_NAME: &str = "storage";
 | 
				
			||||||
 | 
					const WIFI_CONFIG_FILE: &str = "/spiffs/wifi.cfg";
 | 
				
			||||||
 | 
					const CONFIG_FILE: &str = "/spiffs/config.cfg";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[link_section = ".rtc.data"]
 | 
					#[link_section = ".rtc.data"]
 | 
				
			||||||
@@ -64,6 +71,12 @@ pub struct BatteryState {
 | 
				
			|||||||
    state_health_percent: u8
 | 
					    state_health_percent: u8
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct FileSystemSizeInfo{
 | 
				
			||||||
 | 
					    pub total_size: usize,
 | 
				
			||||||
 | 
					    pub used_size: usize,
 | 
				
			||||||
 | 
					    pub free_size: usize
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub enum Sensor{
 | 
					pub enum Sensor{
 | 
				
			||||||
    A,
 | 
					    A,
 | 
				
			||||||
@@ -74,6 +87,8 @@ pub trait PlantCtrlBoardInteraction{
 | 
				
			|||||||
    fn time(&mut self) -> Result<chrono::DateTime<Utc>>;
 | 
					    fn time(&mut self) -> Result<chrono::DateTime<Utc>>;
 | 
				
			||||||
    fn wifi(&mut self, ssid:&str, password:Option<&str>, max_wait:u32) -> Result<()>;
 | 
					    fn wifi(&mut self, ssid:&str, password:Option<&str>, max_wait:u32) -> Result<()>;
 | 
				
			||||||
    fn sntp(&mut self, max_wait:u32) -> Result<chrono::DateTime<Utc>>;
 | 
					    fn sntp(&mut self, max_wait:u32) -> Result<chrono::DateTime<Utc>>;
 | 
				
			||||||
 | 
					    fn mountFileSystem(&mut self) -> Result<()>;
 | 
				
			||||||
 | 
					    fn fileSystemSize(&mut self) -> Result<FileSystemSizeInfo>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn battery_state(&mut self) -> Result<BatteryState>;
 | 
					    fn battery_state(&mut self) -> Result<BatteryState>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -101,7 +116,12 @@ pub trait PlantCtrlBoardInteraction{
 | 
				
			|||||||
    //keep state during deepsleep
 | 
					    //keep state during deepsleep
 | 
				
			||||||
    fn fault(&self,plant:usize, enable:bool);
 | 
					    fn fault(&self,plant:usize, enable:bool);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //config
 | 
				
			||||||
 | 
					    fn is_config_reset(&mut self) -> bool;
 | 
				
			||||||
 | 
					    fn remove_configs(&mut self) -> Result<()>;
 | 
				
			||||||
    fn get_config(&mut self) -> Result<config::Config>;
 | 
					    fn get_config(&mut self) -> Result<config::Config>;
 | 
				
			||||||
 | 
					    fn get_wifi(&mut self) -> Result<config::WifiConfig>;
 | 
				
			||||||
 | 
					    fn set_wifi(&mut self, wifi: &WifiConfig) -> Result<()>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub trait CreatePlantHal<'a> {
 | 
					pub trait CreatePlantHal<'a> {
 | 
				
			||||||
@@ -199,6 +219,7 @@ impl CreatePlantHal<'_> for PlantHal{
 | 
				
			|||||||
        let tank_driver = AdcDriver::new(peripherals.adc1, &Config::new())?;
 | 
					        let tank_driver = AdcDriver::new(peripherals.adc1, &Config::new())?;
 | 
				
			||||||
        let tank_channel: AdcChannelDriver<'_, {attenuation::DB_11}, Gpio39> = AdcChannelDriver::new(peripherals.pins.gpio39)?;
 | 
					        let tank_channel: AdcChannelDriver<'_, {attenuation::DB_11}, Gpio39> = AdcChannelDriver::new(peripherals.pins.gpio39)?;
 | 
				
			||||||
        let solar_is_day = PinDriver::input(peripherals.pins.gpio25)?;
 | 
					        let solar_is_day = PinDriver::input(peripherals.pins.gpio25)?;
 | 
				
			||||||
 | 
					        let boot_button = PinDriver::input(peripherals.pins.gpio0)?;
 | 
				
			||||||
        let light = PinDriver::output(peripherals.pins.gpio26)?;
 | 
					        let light = PinDriver::output(peripherals.pins.gpio26)?;
 | 
				
			||||||
        let main_pump = PinDriver::output(peripherals.pins.gpio23)?;
 | 
					        let main_pump = PinDriver::output(peripherals.pins.gpio23)?;
 | 
				
			||||||
        let tank_power = PinDriver::output(peripherals.pins.gpio27)?;
 | 
					        let tank_power = PinDriver::output(peripherals.pins.gpio27)?;
 | 
				
			||||||
@@ -215,6 +236,7 @@ impl CreatePlantHal<'_> for PlantHal{
 | 
				
			|||||||
            tank_driver : tank_driver,
 | 
					            tank_driver : tank_driver,
 | 
				
			||||||
            tank_channel: tank_channel,
 | 
					            tank_channel: tank_channel,
 | 
				
			||||||
            solar_is_day : solar_is_day,
 | 
					            solar_is_day : solar_is_day,
 | 
				
			||||||
 | 
					            boot_button : boot_button,
 | 
				
			||||||
            light: light,
 | 
					            light: light,
 | 
				
			||||||
            main_pump: main_pump,
 | 
					            main_pump: main_pump,
 | 
				
			||||||
            tank_power: tank_power,
 | 
					            tank_power: tank_power,
 | 
				
			||||||
@@ -235,6 +257,7 @@ pub struct PlantCtrlBoard<'a>{
 | 
				
			|||||||
    tank_driver: AdcDriver<'a, esp_idf_hal::adc::ADC1>,
 | 
					    tank_driver: AdcDriver<'a, esp_idf_hal::adc::ADC1>,
 | 
				
			||||||
    tank_channel: esp_idf_hal::adc::AdcChannelDriver<'a, { attenuation::DB_11 }, Gpio39 >,
 | 
					    tank_channel: esp_idf_hal::adc::AdcChannelDriver<'a, { attenuation::DB_11 }, Gpio39 >,
 | 
				
			||||||
    solar_is_day: PinDriver<'a, esp_idf_hal::gpio::Gpio25, esp_idf_hal::gpio::Input>,
 | 
					    solar_is_day: PinDriver<'a, esp_idf_hal::gpio::Gpio25, esp_idf_hal::gpio::Input>,
 | 
				
			||||||
 | 
					    boot_button: PinDriver<'a, esp_idf_hal::gpio::Gpio0, esp_idf_hal::gpio::Input>,
 | 
				
			||||||
    signal_counter: PcntDriver<'a>,
 | 
					    signal_counter: PcntDriver<'a>,
 | 
				
			||||||
    light: PinDriver<'a, esp_idf_hal::gpio::Gpio26, esp_idf_hal::gpio::Output>,
 | 
					    light: PinDriver<'a, esp_idf_hal::gpio::Gpio26, esp_idf_hal::gpio::Output>,
 | 
				
			||||||
    main_pump: PinDriver<'a, esp_idf_hal::gpio::Gpio23, esp_idf_hal::gpio::Output>,
 | 
					    main_pump: PinDriver<'a, esp_idf_hal::gpio::Gpio23, esp_idf_hal::gpio::Output>,
 | 
				
			||||||
@@ -445,12 +468,72 @@ impl PlantCtrlBoardInteraction for PlantCtrlBoard<'_> {
 | 
				
			|||||||
        return Ok(());
 | 
					        return Ok(());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn get_config(&mut self) -> Result<config::Config> {
 | 
					    fn mountFileSystem(&mut self) -> Result<()> { 
 | 
				
			||||||
        let config_file = File::open("config.cfg")?;
 | 
					        let base_path = CString::new("/spiffs")?;
 | 
				
			||||||
        //serde_json::from_str(&data);
 | 
					        let storage = CString::new(SPIFFS_PARTITION_NAME)?;
 | 
				
			||||||
        bail!("Not implemented");
 | 
					        let conf = esp_idf_sys::esp_vfs_spiffs_conf_t {
 | 
				
			||||||
 | 
					            base_path: base_path.as_ptr(),
 | 
				
			||||||
 | 
					            partition_label: storage.as_ptr(),
 | 
				
			||||||
 | 
					            max_files: 2,
 | 
				
			||||||
 | 
					            format_if_mount_failed: true,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        unsafe {
 | 
				
			||||||
 | 
					            esp_idf_sys::esp!(esp_idf_sys::esp_vfs_spiffs_register(&conf))?;
 | 
				
			||||||
 | 
					            Ok(())
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn fileSystemSize(&mut self) -> Result<FileSystemSizeInfo> {
 | 
				
			||||||
 | 
					        let storage = CString::new(SPIFFS_PARTITION_NAME)?;
 | 
				
			||||||
 | 
					        let mut total_size = 0;
 | 
				
			||||||
 | 
					        let mut used_size = 0;
 | 
				
			||||||
 | 
					        unsafe {
 | 
				
			||||||
 | 
					            esp_idf_sys::esp!(esp_idf_sys::esp_spiffs_info(storage.as_ptr(),&mut total_size,&mut used_size))?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return Ok(FileSystemSizeInfo{total_size, used_size, free_size : total_size - used_size});
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn is_config_reset(&mut self) -> bool {
 | 
				
			||||||
 | 
					        return self.boot_button.get_level() == Level::Low;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn remove_configs(&mut self) -> Result<()> {
 | 
				
			||||||
 | 
					        let wifi_config = Path::new(WIFI_CONFIG_FILE);
 | 
				
			||||||
 | 
					        if wifi_config.exists() {
 | 
				
			||||||
 | 
					            println!("Removing wifi config");
 | 
				
			||||||
 | 
					            std::fs::remove_file(wifi_config)?;    
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        let config = Path::new(CONFIG_FILE);
 | 
				
			||||||
 | 
					        if config.exists() {
 | 
				
			||||||
 | 
					            println!("Removing config");
 | 
				
			||||||
 | 
					            std::fs::remove_file(config)?;    
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn get_wifi(&mut self) -> Result<config::WifiConfig> {
 | 
				
			||||||
 | 
					        let cfg = File::open(WIFI_CONFIG_FILE)?;
 | 
				
			||||||
 | 
					        let config: WifiConfig = serde_json::from_reader(cfg)?;
 | 
				
			||||||
 | 
					        return Ok(config);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn set_wifi(&mut self, wifi: &WifiConfig ) -> Result<()> {
 | 
				
			||||||
 | 
					        let mut cfg = File::create(WIFI_CONFIG_FILE)?;
 | 
				
			||||||
 | 
					        serde_json::to_writer(&mut cfg, &wifi)?;
 | 
				
			||||||
 | 
					        println!("Wrote wifi config {}", wifi);
 | 
				
			||||||
 | 
					        return Ok(());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn get_config(&mut self) -> Result<config::Config> {
 | 
				
			||||||
 | 
					        let mut cfg = File::open(CONFIG_FILE)?;
 | 
				
			||||||
 | 
					        let mut data: [u8; 512] = [0; 512];
 | 
				
			||||||
 | 
					        let read = cfg.read(&mut data)?;
 | 
				
			||||||
 | 
					        println!("Read file {}", from_utf8(&data[0..read])?);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        bail!("todo")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
} 
 | 
					} 
 | 
				
			||||||
		Reference in New Issue
	
	Block a user