adjust rust code to new config file, fix bq34z100 flasher

This commit is contained in:
2024-12-16 02:15:03 +01:00
parent c89a617d9d
commit 74f9c17461
4 changed files with 267 additions and 220 deletions

View File

@@ -1,20 +1,23 @@
//offer ota and config mode
use std::{
collections::VecDeque, fs, io::{BufRead, Read, Write}, str::from_utf8, sync::{atomic::AtomicBool, Arc}
io::{BufRead, BufReader, Read, Write},
str::from_utf8,
sync::{atomic::AtomicBool, Arc},
};
use crate::{espota::OtaUpdate, map_range_moisture, plant_hal::FileInfo, BOARD_ACCESS};
use anyhow::bail;
use chrono::DateTime;
use url::Url;
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 esp_idf_svc::http::server::{Configuration, EspHttpConnection, EspHttpServer, Request};
use heapless::String;
use serde::{Deserialize, Serialize};
use url::Url;
use crate::config::Config;
use crate::config::PlantControllerConfig;
#[derive(Serialize, Debug)]
struct SSIDList<'a> {
@@ -87,8 +90,8 @@ fn get_data(
match a_pct {
Ok(result) => {
a.push(result);
},
Err(err) => {
}
Err(_) => {
a.push(200);
}
}
@@ -97,19 +100,18 @@ fn get_data(
match b_pct {
Ok(result) => {
b.push(result);
},
Err(err) => {
}
Err(_) => {
b.push(200);
}
}
}
let data = LoadData {
rtc: rtc.as_str(),
native: native.as_str(),
moisture_a: a,
moisture_b: b
moisture_b: b,
};
let json = serde_json::to_string(&data)?;
@@ -122,7 +124,7 @@ fn get_config(
let mut board = BOARD_ACCESS.lock().unwrap();
let json = match board.get_config() {
Ok(config) => serde_json::to_string(&config)?,
Err(_) => serde_json::to_string(&Config::default())?,
Err(_) => serde_json::to_string(&PlantControllerConfig::default())?,
};
anyhow::Ok(Some(json))
}
@@ -134,7 +136,7 @@ fn set_config(
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)?;
let config: PlantControllerConfig = serde_json::from_slice(actual_data)?;
let mut board = BOARD_ACCESS.lock().unwrap();
board.set_config(&config)?;
anyhow::Ok(Some("saved".to_owned()))
@@ -176,7 +178,7 @@ fn wifi_scan(
fn list_files(
request: &mut Request<&mut EspHttpConnection>,
) -> Result<Option<std::string::String>, anyhow::Error> {
let filename = query_param(request.uri(),"filename").unwrap_or_default();
let filename = query_param(request.uri(), "filename").unwrap_or_default();
let board = BOARD_ACCESS.lock().unwrap();
let result = board.list_files(&filename);
let file_list_json = serde_json::to_string(&result)?;
@@ -215,17 +217,54 @@ fn ota(
finalizer.restart();
}
fn query_param(uri:&str, param_name:&str) -> Option<std::string::String>{
fn flash_bq(filename: &str, dryrun: bool) -> anyhow::Result<()> {
let mut board = BOARD_ACCESS.lock().unwrap();
let mut toggle = true;
let delay = Delay::new(1);
let file_handle = board.get_file_handle(filename, false)?;
let mut reader = BufReader::with_capacity(512, file_handle).lines();
let mut line = 0;
loop {
board.general_fault(toggle);
toggle = !toggle;
delay.delay_us(2);
line += 1;
match reader.next() {
Some(next) => {
let input = next?;
println!("flashing bq34z100 dryrun:{dryrun} line {line} payload: {input}");
match board.flash_bq34_z100(&input, dryrun) {
Ok(_) => {
println!("ok")
}
Err(err) => {
bail!(
"Error flashing bq34z100 in dryrun: {dryrun} line: {line} error: {err}"
)
}
}
}
None => break,
}
}
println!("Finished flashing file {line} lines processed");
board.general_fault(false);
return anyhow::Ok(());
}
fn query_param(uri: &str, param_name: &str) -> Option<std::string::String> {
println!("{uri} get {param_name}");
let parsed = Url::parse(&format!("http://127.0.0.1/{uri}")).unwrap();
let value = parsed.query_pairs().filter(|it| it.0 == param_name).next();
match value {
Some(found) => {
return Some(found.1.into_owned());
},
None => {
return None
},
}
None => return None,
}
}
@@ -284,18 +323,20 @@ pub fn httpd(_reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
})
.unwrap();
server
.fn_handler("/files", Method::Get, move |request| {
handle_error_to500(request, list_files)
})
.unwrap();
.fn_handler("/files", Method::Get, move |request| {
handle_error_to500(request, list_files)
})
.unwrap();
server
.fn_handler("/file", Method::Get, move |request| {
let filename = query_param(request.uri(),"filename").unwrap();
let file_handle = BOARD_ACCESS.lock().unwrap().get_file_handle(&filename, false);
let filename = query_param(request.uri(), "filename").unwrap();
let file_handle = BOARD_ACCESS
.lock()
.unwrap()
.get_file_handle(&filename, false);
match file_handle {
Ok(mut file_handle) => {
let headers = [("Access-Control-Allow-Origin","*")];
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];
@@ -303,7 +344,10 @@ pub fn httpd(_reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
loop {
let read = file_handle.read(&mut buffer)?;
total_read += read;
println!("sending {read} bytes of {total_read} for file {}", &filename);
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}");
@@ -313,8 +357,7 @@ pub fn httpd(_reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
}
drop(file_handle);
response.flush()?;
},
}
Err(err) => {
//todo set headers here for filename to be error
let error_text = err.to_string();
@@ -327,8 +370,11 @@ pub fn httpd(_reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
.unwrap();
server
.fn_handler("/file", Method::Post, move |mut request| {
let filename = query_param(request.uri(),"filename").unwrap();
let file_handle = BOARD_ACCESS.lock().unwrap().get_file_handle(&filename,true);
let filename = query_param(request.uri(), "filename").unwrap();
let file_handle = BOARD_ACCESS
.lock()
.unwrap()
.get_file_handle(&filename, true);
match file_handle {
Ok(mut file_handle) => {
const BUFFER_SIZE: usize = 512;
@@ -346,7 +392,7 @@ pub fn httpd(_reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
}
}
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();
@@ -357,90 +403,51 @@ pub fn httpd(_reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
anyhow::Ok(())
})
.unwrap();
server
server
.fn_handler("/file", Method::Delete, move |request| {
let filename = query_param(request.uri(),"filename").unwrap();
let filename = query_param(request.uri(), "filename").unwrap();
let copy = filename.clone();
let board = BOARD_ACCESS.lock().unwrap();
match board.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("/flashbattery", Method::Post, move |mut request| {
let mut board = BOARD_ACCESS.lock().unwrap();
let mut buffer: [u8; 128] = [0; 128];
let mut line_buffer: VecDeque<u8> = VecDeque::new();
let is_dry_run = !request.uri().ends_with("?flash=true");
let mut total_read: usize = 0;
let mut toggle = true;
let delay = Delay::new(1);
todo!("Write to storage before attempting to flash!");
loop {
delay.delay_us(2);
let read = request.read(&mut buffer).unwrap();
total_read += read;
if read == 0 {
if line_buffer.len() > 0 {
println!("No further body but no endline");
let mut line = std::string::String::new();
line_buffer.read_to_string(&mut line).unwrap();
let msg = format!("Finished reading, but there is still some leftover in buffer and no full line {line}<br>");
println!("{}", msg);
let mut response = request.into_status_response(400_u16).unwrap();
response.write(msg.as_bytes()).unwrap();
response.flush().unwrap();
return anyhow::Ok(())
.fn_handler("/flashbattery", Method::Post, move |request| {
let filename = query_param(request.uri(),"filename").unwrap();
let dryrun = true;
match flash_bq(&filename, false) {
Ok(_) => {
if !dryrun {
match flash_bq(&filename, true) {
Ok(_) => {
cors_response(request, 200, "Sucessfully flashed bq34z100")?;
},
Err(err) => {
let info = format!("Could not flash bq34z100, could be bricked now! {filename} {err:?}");
cors_response(request, 500, &info)?;
},
}
} else {
cors_response(request, 200, "Sucessfully processed bq34z100")?;
}
break;
}
let to_write = &buffer[0..read];
line_buffer.write_all(to_write).unwrap();
board.general_fault(toggle);
toggle = !toggle;
loop {
let has_line = line_buffer.contains(&b'\n');
if !has_line {
break;
}
let mut line = std::string::String::new();
line_buffer.read_line(&mut line)?;
let line2 = &line[0..line.len()-1];
println!("Processing dry:{} line {}", is_dry_run, line2);
let validate = board.flash_bq34_z100(&line2, is_dry_run);
delay.delay_us(2);
if validate.is_err() {
let mut response = request.into_status_response(400_u16).unwrap();
let err = validate.unwrap_err();
let err_str = err.to_string();
let err_msg = err_str.as_bytes();
println!("Error writing {}", err_str);
response
.write(err_msg)
.unwrap();
return anyhow::Ok(())
}
}
}
let mut response = request.into_status_response(200_u16).unwrap();
let msg = format!("Finished writing {total_read} bytes<br>");
response.write(msg.as_bytes()).unwrap();
board.general_fault(false);
},
Err(err) => {
let info = format!("Could not process firmware file for, bq34z100, refusing to flash! {filename} {err:?}");
cors_response(request, 500, &info)?;
},
};
anyhow::Ok(())
})
.unwrap();
@@ -448,7 +455,7 @@ 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!("index.html"))?;let mut buf = [0_u8; 3072];
response.write(include_bytes!("index.html"))?;
anyhow::Ok(())
})
.unwrap();
@@ -458,7 +465,6 @@ pub fn httpd(_reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
.into_ok_response()?
.write(include_bytes!("favicon.ico"))?;
anyhow::Ok(())
})
.unwrap();
server
@@ -467,14 +473,17 @@ pub fn httpd(_reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
.into_ok_response()?
.write(include_bytes!("bundle.js"))?;
anyhow::Ok(())
})
.unwrap();
server
}
fn cors_response(request: Request<&mut EspHttpConnection>, status: u16, body: &str) -> Result<(), anyhow::Error>{
let headers = [("Access-Control-Allow-Origin","*")];
fn cors_response(
request: Request<&mut EspHttpConnection>,
status: u16,
body: &str,
) -> Result<(), anyhow::Error> {
let headers = [("Access-Control-Allow-Origin", "*")];
let mut response = request.into_response(status, None, &headers)?;
response.write(body.as_bytes())?;
response.flush()?;
@@ -504,4 +513,4 @@ fn handle_error_to500(
}
}
return anyhow::Ok(());
}
}