i2c working, rtc working, eeprom working

This commit is contained in:
2025-09-22 23:44:33 +02:00
parent 1791f463b7
commit 5b0e2b6797
9 changed files with 523 additions and 407 deletions

View File

@@ -1,6 +1,7 @@
//offer ota and config mode
use crate::config::PlantControllerConfig;
use crate::hal::rtc::X25;
use crate::hal::{esp_set_time, esp_time};
use crate::log::LOG_ACCESS;
use crate::tank::{determine_tank_state, TankInfo};
@@ -123,56 +124,9 @@ pub struct NightLampCommand {
// anyhow::Ok(Some(json))
// }
//
//
// fn backup_config(
// request: &mut Request<&mut EspHttpConnection>,
// ) -> Result<Option<std::string::String>, anyhow::Error> {
// let all = read_up_to_bytes_from_request(request, Some(3072))?;
// let mut board = BOARD_ACCESS.lock().expect("board access");
//
// //TODO how to handle progress here? prior versions animated the fault leds while running
// board.board_hal.get_rtc_module().backup_config(&all)?;
// anyhow::Ok(Some("saved".to_owned()))
// }
//
// fn get_backup_config(
// _request: &mut Request<&mut EspHttpConnection>,
// ) -> Result<Option<std::string::String>, anyhow::Error> {
// let mut board = BOARD_ACCESS.lock().expect("board access");
// let json = match board.board_hal.get_rtc_module().get_backup_config() {
// Ok(config) => from_utf8(&config)?.to_owned(),
// Err(err) => {
// log::info!("Error get backup config {:?}", err);
// err.to_string()
// }
// };
// anyhow::Ok(Some(json))
// }
//
// fn backup_info(
// _request: &mut Request<&mut EspHttpConnection>,
// ) -> Result<Option<std::string::String>, anyhow::Error> {
// let mut board = BOARD_ACCESS.lock().expect("Should never fail");
// let header = board.board_hal.get_rtc_module().get_backup_info();
// let json = match header {
// Ok(h) => {
// let timestamp = DateTime::from_timestamp_millis(h.timestamp).unwrap();
// let wbh = WebBackupHeader {
// timestamp: timestamp.to_rfc3339(),
// size: h.size,
// };
// serde_json::to_string(&wbh)?
// }
// Err(err) => {
// let wbh = WebBackupHeader {
// timestamp: err.to_string(),
// size: 0,
// };
// serde_json::to_string(&wbh)?
// }
// };
// anyhow::Ok(Some(json))
// }
//
//
@@ -415,6 +369,10 @@ impl Handler for HttpHandler {
let buf = get_log(conn).await;
Some(200)
}
"/get_backup_config" => {
get_backup_config(conn).await?;
Some(200)
}
&_ => {
let json = match path {
"/version" => Some(get_version_web(conn).await),
@@ -424,7 +382,8 @@ impl Handler for HttpHandler {
"/get_config" => Some(get_config(conn).await),
"/files" => Some(list_files(conn).await),
"/log_localization" => Some(get_log_localization_config(conn).await),
"/wifiscan" => Some(wifi_scan(conn).await),
"/tank" => Some(tank_info(conn).await),
"/backup_info" => Some(backup_info(conn).await),
_ => None,
};
match json {
@@ -438,6 +397,7 @@ impl Handler for HttpHandler {
"/wifiscan" => Some(wifi_scan(conn).await),
"/set_config" => Some(set_config(conn).await),
"/time" => Some(write_time(conn).await),
"/backup_config" => Some(backup_config(conn).await),
"/reboot" => {
let mut board = BOARD_ACCESS.get().await.lock().await;
board.board_hal.get_esp().set_restart_to_conf(true);
@@ -471,101 +431,173 @@ impl Handler for HttpHandler {
}
}
// .fn_handler("/file", Method::Get, move |request| {
// let filename = query_param(request.uri(), "filename").unwrap();
// let file_handle = BOARD_ACCESS
// .lock()
// .unwrap()
// .board_hal
// .get_esp()
// .get_file_handle(&filename, false);
// match file_handle {
// Ok(mut file_handle) => {
// let headers = [("Access-Control-Allow-Origin", "*")];
// let mut response = request.into_response(200, None, &headers)?;
// const BUFFER_SIZE: usize = 512;
// let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
// let mut total_read: usize = 0;
// loop {
// unsafe { vTaskDelay(1) };
// let read = std::io::Read::read(&mut file_handle, &mut buffer)?;
// total_read += read;
// let to_write = &buffer[0..read];
// response.write(to_write)?;
// if read == 0 {
// break;
// }
// }
// log::info!("wrote {total_read} for file {filename}");
// drop(file_handle);
// response.flush()?;
// }
// Err(err) => {
// //todo set headers here for filename to be error
// let error_text = err.to_string();
// log::info!("error handling get file {}", error_text);
// cors_response(request, 500, &error_text)?;
// }
// }
// anyhow::Ok(())
// })
// .unwrap();
// server
// .fn_handler("/file", Method::Post, move |mut request| {
// let filename = query_param(request.uri(), "filename").unwrap();
// let mut board = BOARD_ACCESS.lock().unwrap();
// let file_handle = board.board_hal.get_esp().get_file_handle(&filename, true);
// match file_handle {
// //TODO get free filesystem size, check against during write if not to large
// Ok(mut file_handle) => {
// const BUFFER_SIZE: usize = 512;
// let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
// let mut total_read: usize = 0;
// let mut lastiter = 0;
// loop {
// let iter = (total_read / 1024) % 8;
// if iter != lastiter {
// for i in 0..PLANT_COUNT {
// let _ = board.board_hal.fault(i, iter == i);
// }
// lastiter = iter;
// }
//
// let read = request.read(&mut buffer)?;
// total_read += read;
// let to_write = &buffer[0..read];
// std::io::Write::write(&mut file_handle, to_write)?;
// if read == 0 {
// break;
// }
// }
// cors_response(request, 200, &format!("saved {total_read} bytes"))?;
// }
// Err(err) => {
// //todo set headers here for filename to be error
// let error_text = err.to_string();
// log::info!("error handling get file {}", error_text);
// cors_response(request, 500, &error_text)?;
// }
// }
// drop(board);
// anyhow::Ok(())
// })
// .unwrap();
async fn get_backup_config<T, const N: usize>(
conn: &mut Connection<'_, T, { N }>,
) -> Result<(), FatError>
where
T: Read + Write,
{
let mut checksum = X25.digest();
let mut chunk = 0_usize;
loop {
info!("Chunk {}", chunk);
let mut board = BOARD_ACCESS.get().await.lock().await;
board.board_hal.progress(chunk as u32).await;
let read_chunk = board
.board_hal
.get_rtc_module()
.get_backup_config(chunk)
.await?;
let length = read_chunk.1;
info!("Length {}", length);
if length == 0 {
let check = checksum.finalize();
if check != read_chunk.2 {
if check != read_chunk.2 {
conn.initiate_response(
409,
Some(
format!("Checksum mismatch expected {} got {}", read_chunk.2, check)
.as_str(),
),
&[],
)
.await?;
}
}
info!("file request for backup finished");
break;
}
let data = &read_chunk.0[0..length];
checksum.update(&data);
if length < read_chunk.0.len() {
let check = checksum.finalize();
if check != read_chunk.2 {
conn.initiate_response(
409,
Some(
format!("Checksum mismatch expected {} got {}", read_chunk.2, check)
.as_str(),
),
&[],
)
.await?;
}
info!("file request for backup finished");
break;
}
chunk = chunk + 1;
}
conn.initiate_response(200, Some("OK"), &[]).await?;
async fn tank_info<T, const N: usize>(
request: &mut Connection<'_, T, N>,
let mut chunk = 0;
loop {
let mut board = BOARD_ACCESS.get().await.lock().await;
board.board_hal.progress(chunk as u32).await;
let read_chunk = board
.board_hal
.get_rtc_module()
.get_backup_config(chunk)
.await?;
let length = read_chunk.1;
if length == 0 {
info!("file request for backup finished");
break;
}
let data = &read_chunk.0[0..length];
conn.write_all(data).await?;
if length < read_chunk.0.len() {
info!("file request for backup finished");
break;
}
chunk = chunk + 1;
}
Ok(())
}
async fn backup_config<T, const N: usize>(
conn: &mut Connection<'_, T, N>,
) -> FatResult<Option<String>>
where
T: Read + Write,
{
let mut offset = 0_usize;
let mut buf = [0_u8; 32];
let mut checksum = crate::hal::rtc::X25.digest();
let mut counter = 0;
loop {
let to_write = conn.read(&mut buf).await?;
if to_write == 0 {
info!("backup finished");
break;
} else {
let mut board = BOARD_ACCESS.get().await.lock().await;
board.board_hal.progress(counter).await;
counter = counter + 1;
board
.board_hal
.get_rtc_module()
.backup_config(offset, &buf[0..to_write])
.await?;
checksum.update(&buf[0..to_write]);
}
offset = offset + to_write;
}
let mut board = BOARD_ACCESS.get().await.lock().await;
board
.board_hal
.get_rtc_module()
.backup_config_finalize(checksum.finalize(), offset)
.await?;
Ok(Some("saved".to_owned()))
}
async fn backup_info<T, const N: usize>(
_request: &mut Connection<'_, T, N>,
) -> Result<Option<String>, FatError>
where
T: Read + Write,
{
let mut board = BOARD_ACCESS.get().await.lock().await;
determine_tank_state(&mut board);
//should be multsampled
let header = board.board_hal.get_rtc_module().get_backup_info().await;
let json = match header {
Ok(h) => {
let timestamp = DateTime::from_timestamp_millis(h.timestamp).unwrap();
let wbh = WebBackupHeader {
timestamp: timestamp.to_rfc3339(),
size: h.size,
};
serde_json::to_string(&wbh)?
}
Err(err) => {
let wbh = WebBackupHeader {
timestamp: err.to_string(),
size: 0,
};
serde_json::to_string(&wbh)?
}
};
Ok(Some(json))
}
async fn tank_info<T, const N: usize>(
_request: &mut Connection<'_, T, N>,
) -> Result<Option<String>, FatError>
where
T: Read + Write,
{
let mut board = BOARD_ACCESS.get().await.lock().await;
let tank_state = determine_tank_state(&mut board).await;
//should be multisampled
let sensor = board.board_hal.get_tank_sensor()?;
let water_temp = sensor.water_temperature_c().await?;
Ok(Some(serde_json::to_string(&tank_info.as_mqtt_info(
let water_temp: FatResult<f32> = sensor.water_temperature_c().await;
Ok(Some(serde_json::to_string(&tank_state.as_mqtt_info(
&board.board_hal.get_config().tank,
&water_temp,
))?))
@@ -892,29 +924,6 @@ pub async fn httpd(reboot_now: Arc<AtomicBool>, stack: Stack<'static>) {
// server
//
// server
// .fn_handler("/file", Method::Delete, move |request| {
// let filename = query_param(request.uri(), "filename").unwrap();
// let copy = filename.clone();
// let mut board = BOARD_ACCESS.lock().unwrap();
// match board.board_hal.get_esp().delete_file(&filename) {
// Ok(_) => {
// let info = format!("Deleted file {copy}");
// cors_response(request, 200, &info)?;
// }
// Err(err) => {
// let info = format!("Could not delete file {copy} {err:?}");
// cors_response(request, 400, &info)?;
// }
// }
// anyhow::Ok(())
// })
// .unwrap();
// server
// .fn_handler("/file", Method::Options, |request| {
// cors_response(request, 200, "")
// })
// .unwrap();
// unsafe { vTaskDelay(1) };
// server
// .fn_handler("/", Method::Get, move |request| {