diff --git a/rust/src/webserver/mod.rs b/rust/src/webserver/mod.rs index 8133de3..7f128aa 100644 --- a/rust/src/webserver/mod.rs +++ b/rust/src/webserver/mod.rs @@ -30,59 +30,80 @@ use core::result::Result::Ok; use core::sync::atomic::{AtomicBool, Ordering}; use edge_http::io::server::{Connection, Handler, Server}; use edge_http::Method; -use edge_nal::TcpBind; use edge_nal::io::{Read, Write}; +use edge_nal::TcpBind; use edge_nal_embassy::{Tcp, TcpBuffers}; use embassy_net::Stack; use embassy_time::Instant; -use log::info; +use log::{error, info}; -// fn ota( -// request: &mut Request<&mut EspHttpConnection>, -// ) -> Result, anyhow::Error> { -// let mut board = BOARD_ACCESS.lock().unwrap(); -// let mut ota = OtaUpdate::begin()?; -// log::info!("start ota"); -// -// //having a larger buffer is not really faster, requires more stack and prevents the progress bar from working ;) -// 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 read = request.read(&mut buffer)?; -// total_read += read; -// let to_write = &buffer[0..read]; -// //delay for watchdog and wifi stuff -// board.board_hal.get_esp().delay.delay_ms(1); -// -// let iter = (total_read / 1024) % 8; -// if iter != lastiter { -// board.board_hal.general_fault(iter % 5 == 0); -// for i in 0..PLANT_COUNT { -// let _ = board.board_hal.fault(i, iter == i); -// } -// lastiter = iter; -// } -// -// ota.write(to_write)?; -// if read == 0 { -// break; -// } -// } -// log::info!("wrote bytes ota {total_read}"); -// log::info!("finish ota"); -// let partition = ota.raw_partition(); -// log::info!("finalizing and changing boot partition to {partition:?}"); -// -// let mut finalizer = ota.finalize()?; -// log::info!("changing boot partition"); -// board.board_hal.get_esp().set_restart_to_conf(true); -// drop(board); -// finalizer.set_as_boot_partition()?; -// anyhow::Ok(None) -// } -// +pub(crate) async fn ota_operations( + conn: &mut Connection<'_, T, { N }>, + method: Method, +) -> Result, FatError> +where + T: Read + Write, +{ + Ok(match method { + Method::Options => { + conn.initiate_response( + 200, + Some("OK"), + &[ + ("Access-Control-Allow-Origin", "*"), + ("Access-Control-Allow-Headers", "*"), + ("Access-Control-Allow-Methods", "*"), + ], + ) + .await?; + Some(200) + } + Method::Post => { + let mut offset = 0_usize; + let mut chunk = 0; + loop { + let buf = read_up_to_bytes_from_request(conn, Some(4096)).await?; + if buf.is_empty() { + info!("file request for ota finished"); + let mut board = BOARD_ACCESS.get().await.lock().await; + board.board_hal.get_esp().finalize_ota().await?; + break; + } else { + let mut board = BOARD_ACCESS.get().await.lock().await; + board.board_hal.progress(chunk as u32).await; + // Erase next block if we are at a 4K boundary (including the first block at offset 0) + board + .board_hal + .get_esp() + .write_ota(offset as u32, &buf) + .await?; + } + offset += buf.len(); + chunk += 1; + } + BOARD_ACCESS + .get() + .await + .lock() + .await + .board_hal + .clear_progress() + .await; + conn.initiate_response( + 200, + Some("OK"), + &[ + ("Access-Control-Allow-Origin", "*"), + ("Access-Control-Allow-Headers", "*"), + ("Access-Control-Allow-Methods", "*"), + ], + ) + .await?; + Some(200) + } + _ => None, + }) +} struct HTTPRequestRouter { reboot_now: Arc, @@ -105,7 +126,12 @@ impl Handler for HTTPRequestRouter { let path = headers.path; let prefix = "/file?filename="; - let status = if path.starts_with(prefix) { + let status = if path == "/ota" { + ota_operations(conn, method).await.map_err(|e| { + error!("Error handling ota: {e}"); + e + })? + } else if path.starts_with(prefix) { file_operations(conn, method, &path, &prefix).await? } else { match method {