initial file browser work

This commit is contained in:
2024-11-20 01:14:39 +01:00
parent 8218c4b9a6
commit 9f249af430
3 changed files with 145 additions and 16 deletions

View File

@@ -2,17 +2,17 @@
use std::{
collections::VecDeque,
io::{BufRead, Read, Write},
io::{BufRead, Read, Seek, Write},
str::from_utf8,
sync::{atomic::AtomicBool, Arc},
};
use crate::{espota::OtaUpdate, map_range_moisture, plant_hal::PLANT_COUNT, BOARD_ACCESS};
use crate::{espota::OtaUpdate, map_range_moisture, plant_hal::{FileInfo, PLANT_COUNT}, BOARD_ACCESS};
use chrono::DateTime;
use core::result::Result::Ok;
use embedded_svc::http::Method;
use esp_idf_hal::delay::Delay;
use esp_idf_svc::http::server::{Configuration, EspHttpConnection, EspHttpServer, Request};
use embedded_svc::http::{Method, Query};
use esp_idf_hal::{delay::Delay, io::Write};
use esp_idf_svc::{fs, http::server::{Configuration, EspHttpConnection, EspHttpServer, Request}};
use heapless::String;
use serde::{Deserialize, Serialize};
@@ -23,6 +23,11 @@ struct SSIDList<'a> {
ssids: Vec<&'a String<32>>,
}
#[derive(Serialize, Debug)]
struct FileList {
file: Vec<FileInfo>,
}
#[derive(Serialize, Debug)]
struct VersionInfo<'a> {
git_hash: &'a str,
@@ -170,6 +175,15 @@ fn wifi_scan(
anyhow::Ok(Some(ssid_json))
}
fn list_files(
_request: &mut Request<&mut EspHttpConnection>,
) -> Result<Option<std::string::String>, anyhow::Error> {
let board = BOARD_ACCESS.lock().unwrap();
let result = board.list_files()?;
let file_list_json = serde_json::to_string(&FileList { file: result })?;
return anyhow::Ok(Some(file_list_json));
}
fn ota(
request: &mut Request<&mut EspHttpConnection>,
) -> Result<Option<std::string::String>, anyhow::Error> {
@@ -252,10 +266,96 @@ pub fn httpd(_reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
.unwrap();
server
.fn_handler("/set_config", Method::Post, move |mut request| {
.fn_handler("/set_config", Method::Post, move |request| {
handle_error_to500(request, set_config)
})
.unwrap();
server
.fn_handler("/list_files", Method::Get, move |request| {
handle_error_to500(request, list_files)
})
.unwrap();
server
.fn_handler("/get_file", Method::Get, move |request| {
let filename:String = request.uri().magic_here().get("filename");
let file_handle = BOARD_ACCESS.lock().unwrap().get_file_handle(filename);
match file_handle {
Ok(file_handle) => {
let mut response = request.into_ok_response()?;
const BUFFER_SIZE: usize = 512;
let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
let mut total_read: usize = 0;
loop {
let read = file_handle.read(&mut buffer)?;
total_read += read;
println!("sending {read} bytes of {total_read} for file {filename}");
let to_write = &buffer[0..read];
response.write(to_write)?;
println!("wrote {read} bytes of {total_read} for file {filename}");
if read == 0 {
break;
}
}
response.flush()?;
},
Err(err) => {
//todo set headers here for filename to be error
let error_text = err.to_string();
println!("error handling get file {}", error_text);
request
.into_status_response(500)?
.write(error_text.as_bytes())?;
}
}
anyhow::Ok(())
})
.unwrap();
server
.fn_handler("/put_file", Method::Post, move |request| {
let filename:String = request.uri().magic_here().get("filename");
let file_handle = BOARD_ACCESS.lock().unwrap().get_file_handle(filename);
match file_handle {
Ok(file_handle) => {
const BUFFER_SIZE: usize = 512;
let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
let mut total_read: usize = 0;
loop {
let read = request.read(&mut buffer)?;
total_read += read;
println!("sending {read} bytes of {total_read} for upload {filename}");
let to_write = &buffer[0..read];
file_handle.write(to_write)?;
println!("wrote {read} bytes of {total_read} for upload {filename}");
if read == 0 {
break;
}
}
request.into_ok_response().unwrap().write(format!("saved {total_read} bytes").as_bytes());
},
Err(err) => {
//todo set headers here for filename to be error
let error_text = err.to_string();
println!("error handling get file {}", error_text);
request
.into_status_response(500)?
.write(error_text.as_bytes())?;
}
}
anyhow::Ok(())
})
.unwrap();
server
.fn_handler("/get_file", Method::Post, move |request| {
handle_error_to500(request, set_config)
})
.unwrap();
server
.fn_handler("/put_file", Method::Post, move |request| {
handle_error_to500(request, set_config)
})
.unwrap();
server
.fn_handler("/flashbattery", Method::Post, move |mut request| {
@@ -327,14 +427,12 @@ pub fn httpd(_reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
server
.fn_handler("/", Method::Get, move |request| {
let mut response = request.into_ok_response()?;
response.write(include_bytes!("config.html"))?;
anyhow::Ok(())
})
.unwrap();
server
.fn_handler("/bundle.js", Method::Get, |request| {
request
.into_ok_response()?
response.write(include_bytes!("config.html"))?;let mut buf = [0_u8; 3072];
let read = request.read(&mut buf)?;
let actual_data = &buf[0..read];
println!("Raw data {}", from_utf8(actual_data).unwrap());
let config: Config = serde_json::from_slice(actual_data)?;
.write(include_bytes!("bundle.js"))?;
anyhow::Ok(())
})
@@ -345,6 +443,7 @@ pub fn httpd(_reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
.into_ok_response()?
.write(include_bytes!("favicon.ico"))?;
anyhow::Ok(())
})
.unwrap();
server