remove anyhow

This commit is contained in:
2025-09-22 01:49:25 +02:00
parent c94f5bdb45
commit 1791f463b7
21 changed files with 2268 additions and 1982 deletions

View File

@@ -1,33 +1,31 @@
use crate::config::{NetworkConfig, PlantControllerConfig};
use crate::hal::{GW_IP_ADDR_ENV, PLANT_COUNT, TIME_ACCESS};
use crate::log::{ LogArray, LogMessage, LOG_ACCESS};
use crate::STAY_ALIVE;
use anyhow::{anyhow, bail, Context};
use chrono::{DateTime, FixedOffset, Utc};
use crate::log::{LogMessage, LOG_ACCESS};
use crate::{bail, STAY_ALIVE};
use chrono::{DateTime, Utc};
use serde::Serialize;
use crate::hal::little_fs2storage_adapter::LittleFs2Filesystem;
use crate::FatError::{ContextExt, FatError, FatResult};
use alloc::string::ToString;
use alloc::sync::Arc;
use alloc::{format, string::String, vec::Vec};
use core::marker::PhantomData;
use core::net::{IpAddr, Ipv4Addr};
use core::str::FromStr;
use embassy_executor::{Spawner};
use embassy_executor::Spawner;
use embassy_net::{Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::mutex::Mutex;
use embassy_time::{Duration, Instant, Timer};
use embassy_time::{Duration, Timer};
use embedded_storage::nor_flash::ReadNorFlash;
use embedded_storage::Storage;
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState, Slot};
use esp_bootloader_esp_idf::partitions::{Error, FlashRegion, PartitionEntry, PartitionTable};
use esp_bootloader_esp_idf::ota::{Ota, OtaImageState};
use esp_bootloader_esp_idf::partitions::FlashRegion;
use esp_hal::gpio::Input;
use esp_hal::rng::Rng;
use esp_hal::rtc_cntl::Rtc;
use esp_hal::rtc_cntl::sleep::RtcSleepConfig;
use esp_hal::system::software_reset;
use esp_println::{println};
use esp_println::println;
use esp_storage::FlashStorage;
use esp_wifi::wifi::{
AccessPointConfiguration, AccessPointInfo, Configuration, Interfaces, ScanConfig,
@@ -35,7 +33,7 @@ use esp_wifi::wifi::{
};
use littlefs2::fs::Filesystem;
use littlefs2_core::{DynFile, FileType, PathBuf, SeekFrom};
use log::{info};
use log::info;
#[esp_hal::ram(rtc_fast, persistent)]
static mut LAST_WATERING_TIMESTAMP: [i64; PLANT_COUNT] = [0; PLANT_COUNT];
@@ -113,12 +111,10 @@ macro_rules! mk_static {
}
impl Esp<'_> {
pub(crate) async fn delete_file(&self, filename: String) -> anyhow::Result<()> {
pub(crate) async fn delete_file(&self, filename: String) -> FatResult<()> {
let file = PathBuf::try_from(filename.as_str()).unwrap();
let access = self.fs.lock().await;
access
.remove(&*file)
.map_err(|err| anyhow!("Could not delete file: {:?}", err))?;
access.remove(&*file)?;
Ok(())
}
pub(crate) async fn write_file(
@@ -126,11 +122,10 @@ impl Esp<'_> {
filename: String,
offset: u32,
buf: &[u8],
) -> anyhow::Result<()> {
let file = PathBuf::try_from(filename.as_str()).unwrap();
) -> Result<(), FatError> {
let file = PathBuf::try_from(filename.as_str())?;
let access = self.fs.lock().await;
info!("write file {} at offset {}", filename, offset);
match access.open_file_with_options_and_then(
access.open_file_with_options_and_then(
|options| options.read(true).write(true).create(true),
&*file,
|file| {
@@ -138,51 +133,45 @@ impl Esp<'_> {
file.write(buf)?;
Ok(())
},
) {
Ok(_) => Ok(()),
Err(err) => {
bail!(format!("{err:?}"))
}
}
)?;
Ok(())
}
pub async fn get_size(&mut self, filename: String) -> FatResult<usize> {
let file = PathBuf::try_from(filename.as_str())?;
let access = self.fs.lock().await;
let data = access.metadata(&*file)?;
Ok(data.len())
}
pub(crate) async fn get_file(
&mut self,
filename: String,
chunk: u32,
) -> anyhow::Result<([u8; 128], usize)> {
) -> FatResult<([u8; 512], usize)> {
use littlefs2::io::Error as lfs2Error;
let file = PathBuf::try_from(filename.as_str()).unwrap();
let file = PathBuf::try_from(filename.as_str())?;
let access = self.fs.lock().await;
let mut buf = [0_u8; 128];
let mut buf = [0_u8; 512];
let mut read = 0;
let offset = chunk * 128;
info!("read file {} at offset {}", filename, offset);
match access.open_file_with_options_and_then(
let offset = chunk * buf.len() as u32;
access.open_file_with_options_and_then(
|options| options.read(true),
&*file,
|file| {
let length = file.len()? as u32;
info!("file length {}", length);
if length == 0 {
Err(lfs2Error::IO)
} else if length > offset {
file.seek(SeekFrom::Start(offset))?;
info!("seek to {}", offset);
read = file.read(&mut buf)?;
info!("read {} bytes", read);
Ok(())
} else {
//exactly at end, do nothing
Ok(())
}
},
) {
Ok(_) => {}
Err(err) => {
bail!(format!("{err:?}"))
}
}
)?;
Ok((buf, read))
}
@@ -219,7 +208,7 @@ impl Esp<'_> {
pub(crate) fn mode_override_pressed(&mut self) -> bool {
self.boot_button.is_low()
}
pub(crate) async fn sntp(&mut self, _max_wait_ms: u32) -> anyhow::Result<DateTime<Utc>> {
pub(crate) async fn sntp(&mut self, _max_wait_ms: u32) -> FatResult<DateTime<Utc>> {
//let sntp = sntp::EspSntp::new_default()?;
//let mut counter = 0;
//while sntp.get_sync_status() != SyncStatus::Completed {
@@ -233,19 +222,15 @@ impl Esp<'_> {
todo!();
}
pub async fn flash_ota(&mut self) -> anyhow::Result<()> {
pub async fn flash_ota(&mut self) -> FatResult<()> {
let capacity = self.ota_next.capacity();
bail!("not implemented")
}
pub(crate) async fn wifi_scan(&mut self) -> anyhow::Result<Vec<AccessPointInfo>> {
pub(crate) async fn wifi_scan(&mut self) -> FatResult<Vec<AccessPointInfo>> {
info!("start wifi scan");
let mut lock = self
.controller
.try_lock()
.map_err(|_| anyhow!("Could not lock wifi controller, currently in use"))?;
let mut lock = self.controller.try_lock()?;
info!("start wifi scan lock");
let scan_config = ScanConfig {
ssid: None,
@@ -254,10 +239,7 @@ impl Esp<'_> {
show_hidden: false,
scan_type: ScanTypeConfig::Passive(core::time::Duration::from_secs(2)),
};
let rv = lock
.scan_with_config_async(scan_config)
.await
.map_err(|err| anyhow!("Could not scan wifi: {:?}", err))?;
let rv = lock.scan_with_config_async(scan_config).await?;
info!("end wifi scan lock");
Ok(rv)
}
@@ -294,7 +276,7 @@ impl Esp<'_> {
unsafe { CONSECUTIVE_WATERING_PLANT[plant] }
}
pub(crate) fn get_restart_to_conf(&mut self) -> bool {
unsafe { RESTART_TO_CONF == 1}
unsafe { RESTART_TO_CONF == 1 }
}
pub(crate) fn set_restart_to_conf(&mut self, to_conf: bool) {
unsafe {
@@ -306,7 +288,7 @@ impl Esp<'_> {
}
}
pub(crate) async fn wifi_ap(&mut self) -> anyhow::Result<Stack<'static>> {
pub(crate) async fn wifi_ap(&mut self) -> FatResult<Stack<'static>> {
let ssid = match self.load_config().await {
Ok(config) => config.network.ap_ssid.as_str().to_string(),
Err(_) => "PlantCtrl Emergency Mode".to_string(),
@@ -358,7 +340,7 @@ impl Esp<'_> {
.config_v4()
.inspect(|c| println!("ipv4 config: {c:?}"));
anyhow::Ok(stack.clone())
Ok(stack.clone())
}
pub async fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
@@ -376,7 +358,6 @@ impl Esp<'_> {
if duration_in_ms == 0 {
software_reset();
} else {
loop {
info!("todo deepsleep")
}
@@ -390,11 +371,19 @@ impl Esp<'_> {
//};
}
pub(crate) async fn wifi(&mut self, network_config: &NetworkConfig) -> anyhow::Result<IpInfo> {
let _ssid = network_config
.ssid
.clone()
.ok_or(anyhow!("No ssid configured"))?;
pub(crate) async fn wifi(&mut self, network_config: &NetworkConfig) -> FatResult<IpInfo> {
let _ssid = network_config.ssid.clone();
match &_ssid {
Some(ssid) => {
if ssid.is_empty() {
bail!("Wifi ssid was empty")
}
}
None => {
bail!("Wifi ssid was empty")
}
}
let _ssid = _ssid.unwrap();
let _password = network_config.password.clone();
let _max_wait = network_config.max_wait;
bail!("todo")
@@ -452,59 +441,32 @@ impl Esp<'_> {
// log(LogMessage::WifiInfo, 0, 0, "", &format!("{address:?}"));
// anyhow::Ok(address)
}
pub(crate) async fn load_config(&mut self) -> anyhow::Result<PlantControllerConfig> {
pub(crate) async fn load_config(&mut self) -> FatResult<PlantControllerConfig> {
let cfg = PathBuf::try_from(CONFIG_FILE).unwrap();
match self.fs.lock().await.read::<4096>(&cfg) {
Ok(data) => {
let config: PlantControllerConfig = serde_json::from_slice(&data)?;
anyhow::Ok(config)
}
Err(err) => {
bail!(format!("{err:?}"))
}
}
let data = self.fs.lock().await.read::<4096>(&cfg)?;
let config: PlantControllerConfig = serde_json::from_slice(&data)?;
return Ok(config);
}
pub(crate) async fn save_config(&mut self, config: Vec<u8>) -> anyhow::Result<()> {
pub(crate) async fn save_config(&mut self, config: Vec<u8>) -> FatResult<()> {
let filesystem = self.fs.lock().await;
let cfg = PathBuf::try_from(CONFIG_FILE).unwrap();
match filesystem.write(&cfg, &*config) {
Ok(_) => {}
Err(err) => {
bail!(format!("{err:?}"))
}
}
anyhow::Ok(())
let cfg = PathBuf::try_from(CONFIG_FILE)?;
filesystem.write(&cfg, &*config)?;
Ok(())
}
async fn file_system_size(&mut self) -> anyhow::Result<FileSystemSizeInfo> {
bail!("fail");
// let storage = CString::new(Self::SPIFFS_PARTITION_NAME)?;
// let mut total_size = 0;
// let mut used_size = 0;
// unsafe {
// esp_idf_sys::esp!(esp_spiffs_info(
// storage.as_ptr(),
// &mut total_size,
// &mut used_size
// ))?;
// }
// anyhow::Ok(FileSystemSizeInfo {
// total_size,
// used_size,
// free_size: total_size - used_size,
// })
}
pub(crate) async fn list_files(&self) -> anyhow::Result<FileList> {
pub(crate) async fn list_files(&self) -> FatResult<FileList> {
let path = PathBuf::new();
let fs = self.fs.lock().await;
let free_size = fs.available_space()?;
let total_size = fs.total_space();
let mut result = FileList {
total: 0,
used: 0,
total: total_size,
used: total_size - free_size,
files: Vec::new(),
};
match self.fs.lock().await.read_dir_and_then(&path, |dir| {
fs.read_dir_and_then(&path, |dir| {
for entry in dir {
let e = entry?;
if e.file_type() == FileType::File {
@@ -514,29 +476,11 @@ impl Esp<'_> {
});
}
}
Result::Ok(())
}) {
Ok(_) => {}
Err(err) => {
bail!(format!("{err:?}"))
}
}
Ok(())
})?;
Ok(result)
}
// pub(crate) async fn get_file_handle(
// &self,
// filename: &str,
// write: bool,
// ) -> anyhow::Result<File> {
// let filepath = Path::new(Self::BASE_PATH).join(Path::new(filename));
// anyhow::Ok(if write {
// File::create(filepath)?
// } else {
// File::open(filepath)?
// })
// }
pub(crate) async fn init_rtc_deepsleep_memory(
&self,
init_rtc_store: bool,
@@ -558,22 +502,28 @@ impl Esp<'_> {
if to_config_mode {
RESTART_TO_CONF = 1;
}
LOG_ACCESS.lock().await.log(
LogMessage::RestartToConfig,
RESTART_TO_CONF as u32,
0,
"",
"",
).await
;
LOG_ACCESS.lock().await.log(
LogMessage::LowVoltage,
LOW_VOLTAGE_DETECTED as u32,
0,
"",
"",
).await
;
LOG_ACCESS
.lock()
.await
.log(
LogMessage::RestartToConfig,
RESTART_TO_CONF as u32,
0,
"",
"",
)
.await;
LOG_ACCESS
.lock()
.await
.log(
LogMessage::LowVoltage,
LOW_VOLTAGE_DETECTED as u32,
0,
"",
"",
)
.await;
for i in 0..PLANT_COUNT {
log::info!(
"LAST_WATERING_TIMESTAMP[{}] = UTC {}",
@@ -592,7 +542,7 @@ impl Esp<'_> {
}
}
pub(crate) async fn mqtt(&mut self, network_config: &NetworkConfig) -> anyhow::Result<()> {
pub(crate) async fn mqtt(&mut self, network_config: &NetworkConfig) -> FatResult<()> {
let base_topic = network_config
.base_topic
.as_ref()
@@ -756,11 +706,7 @@ impl Esp<'_> {
// }
// bail!("Mqtt did not fire connection callback in time");
}
pub(crate) async fn mqtt_publish(
&mut self,
_subtopic: &str,
_message: &[u8],
) -> anyhow::Result<()> {
pub(crate) async fn mqtt_publish(&mut self, _subtopic: &str, _message: &[u8]) -> FatResult<()> {
bail!("todo");
//
// if self.mqtt_client.is_none() {