remove anyhow
This commit is contained in:
@@ -1,23 +1,25 @@
|
||||
//offer ota and config mode
|
||||
|
||||
use crate::config::PlantControllerConfig;
|
||||
use crate::{get_version, log::LogMessage, BOARD_ACCESS};
|
||||
use crate::hal::{esp_set_time, esp_time};
|
||||
use crate::log::LOG_ACCESS;
|
||||
use crate::tank::{determine_tank_state, TankInfo};
|
||||
use crate::FatError::{FatError, FatResult};
|
||||
use crate::{bail, get_version, log::LogMessage, BOARD_ACCESS};
|
||||
use alloc::borrow::ToOwned;
|
||||
use alloc::format;
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::sync::Arc;
|
||||
use alloc::vec::Vec;
|
||||
use anyhow::{bail};
|
||||
use chrono::DateTime;
|
||||
use core::fmt::{Debug, Display};
|
||||
use core::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use core::result::Result::Ok;
|
||||
use core::str::from_utf8;
|
||||
use core::sync::atomic::{AtomicBool, Ordering};
|
||||
use chrono::DateTime;
|
||||
use edge_http::io::server::{Connection, Handler, Server};
|
||||
use edge_http::io::Error;
|
||||
use edge_http::Method;
|
||||
use edge_nal::{TcpBind};
|
||||
use edge_nal::TcpBind;
|
||||
use edge_nal_embassy::{Tcp, TcpBuffers};
|
||||
use embassy_net::Stack;
|
||||
use embassy_time::Instant;
|
||||
@@ -25,8 +27,6 @@ use embedded_io_async::{Read, Write};
|
||||
use esp_println::println;
|
||||
use log::info;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::hal::{esp_set_time, esp_time};
|
||||
use crate::log::{LOG_ACCESS};
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
struct SSIDList {
|
||||
@@ -191,23 +191,6 @@ pub struct NightLampCommand {
|
||||
// anyhow::Ok(Some(serde_json::to_string(&pump_result)?))
|
||||
// }
|
||||
//
|
||||
// fn tank_info(
|
||||
// _request: &mut Request<&mut EspHttpConnection>,
|
||||
// ) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||
// let mut board = BOARD_ACCESS.lock().unwrap();
|
||||
// let tank_info = determine_tank_state(&mut board);
|
||||
// //should be multsampled
|
||||
//
|
||||
// let water_temp = board
|
||||
// .board_hal
|
||||
// .get_tank_sensor()
|
||||
// .context("no sensor")
|
||||
// .and_then(|f| f.water_temperature_c());
|
||||
// Ok(Some(serde_json::to_string(&tank_info.as_mqtt_info(
|
||||
// &board.board_hal.get_config().tank,
|
||||
// &water_temp,
|
||||
// ))?))
|
||||
// }
|
||||
//
|
||||
// fn night_lamp_test(
|
||||
// request: &mut Request<&mut EspHttpConnection>,
|
||||
@@ -285,12 +268,12 @@ struct HttpHandler {
|
||||
}
|
||||
|
||||
impl Handler for HttpHandler {
|
||||
type Error<E: core::fmt::Debug> = Error<E>;
|
||||
type Error<E: Debug> = FatError;
|
||||
async fn handle<'a, T, const N: usize>(
|
||||
&self,
|
||||
_task_id: impl Display + Copy,
|
||||
conn: &mut Connection<'a, T, N>,
|
||||
) -> anyhow::Result<(), Self::Error<T::Error>>
|
||||
) -> Result<(), FatError>
|
||||
where
|
||||
T: Read + Write,
|
||||
{
|
||||
@@ -303,46 +286,55 @@ impl Handler for HttpHandler {
|
||||
let prefix = "/file?filename=";
|
||||
let status = if path.starts_with(prefix) {
|
||||
let filename = &path[prefix.len()..];
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
info!("file request for {} with method {}", filename, method);
|
||||
match method {
|
||||
Method::Delete => {
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
board
|
||||
.board_hal
|
||||
.get_esp()
|
||||
.delete_file(filename.to_owned())
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
Some(200)
|
||||
}
|
||||
Method::Get => {
|
||||
let disp = format!("attachment; filename=\"{filename}\"");
|
||||
let size = {
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
board
|
||||
.board_hal
|
||||
.get_esp()
|
||||
.get_size(filename.to_owned())
|
||||
.await?
|
||||
};
|
||||
|
||||
conn.initiate_response(
|
||||
200,
|
||||
Some("OK"),
|
||||
&[
|
||||
("Content-Type", "application/octet-stream"),
|
||||
("Content-Disposition", disp.as_str()),
|
||||
("Content-Length", &format!("{}", size)),
|
||||
],
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut chunk = 0;
|
||||
loop {
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
let read_chunk = board
|
||||
.board_hal
|
||||
.get_esp()
|
||||
.get_file(filename.to_owned(), chunk)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
let length = read_chunk.1;
|
||||
info!("read {} bytes for file request for {}", length, filename);
|
||||
if length == 0 {
|
||||
info!("file request for {} finished", filename);
|
||||
break;
|
||||
}
|
||||
let data = &read_chunk.0[0..length];
|
||||
conn.write_all(data).await?;
|
||||
if length < 128 {
|
||||
if length < read_chunk.0.len() {
|
||||
info!("file request for {} finished", filename);
|
||||
break;
|
||||
}
|
||||
@@ -351,12 +343,16 @@ impl Handler for HttpHandler {
|
||||
Some(200)
|
||||
}
|
||||
Method::Post => {
|
||||
//ensure file is deleted, otherwise we would need to truncate the file which will not work with streaming
|
||||
let _ = board
|
||||
.board_hal
|
||||
.get_esp()
|
||||
.delete_file(filename.to_owned())
|
||||
.await;
|
||||
{
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
//ensure file is deleted, otherwise we would need to truncate the file which will not work with streaming
|
||||
let _ = board
|
||||
.board_hal
|
||||
.get_esp()
|
||||
.delete_file(filename.to_owned())
|
||||
.await;
|
||||
}
|
||||
|
||||
let mut offset = 0_usize;
|
||||
loop {
|
||||
let mut buf = [0_u8; 1024];
|
||||
@@ -365,16 +361,12 @@ impl Handler for HttpHandler {
|
||||
info!("file request for {} finished", filename);
|
||||
break;
|
||||
} else {
|
||||
info!(
|
||||
"writing {} bytes for file request for {}",
|
||||
to_write, filename
|
||||
);
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
board
|
||||
.board_hal
|
||||
.get_esp()
|
||||
.write_file(filename.to_owned(), offset as u32, &buf[0..to_write])
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
}
|
||||
offset = offset + to_write
|
||||
}
|
||||
@@ -397,25 +389,32 @@ impl Handler for HttpHandler {
|
||||
Some(200)
|
||||
}
|
||||
"/" => {
|
||||
conn.initiate_response(200, Some("OK"), &[("Content-Type", "text/html")])
|
||||
.await?;
|
||||
conn.write_all(include_bytes!("index.html")).await?;
|
||||
conn.initiate_response(
|
||||
200,
|
||||
Some("OK"),
|
||||
&[("Content-Type", "text/html"), ("Content-Encoding", "gzip")],
|
||||
)
|
||||
.await?;
|
||||
conn.write_all(include_bytes!("index.html.gz")).await?;
|
||||
Some(200)
|
||||
}
|
||||
"/bundle.js" => {
|
||||
conn.initiate_response(
|
||||
200,
|
||||
Some("OK"),
|
||||
&[("Content-Type", "text/javascript")],
|
||||
&[
|
||||
("Content-Type", "text/javascript"),
|
||||
("Content-Encoding", "gzip"),
|
||||
],
|
||||
)
|
||||
.await?;
|
||||
conn.write_all(include_bytes!("bundle.js")).await?;
|
||||
conn.write_all(include_bytes!("bundle.js.gz")).await?;
|
||||
Some(200)
|
||||
}
|
||||
"/log" => {
|
||||
let buf = get_log(conn).await;
|
||||
Some(200)
|
||||
},
|
||||
}
|
||||
&_ => {
|
||||
let json = match path {
|
||||
"/version" => Some(get_version_web(conn).await),
|
||||
@@ -554,23 +553,40 @@ impl Handler for HttpHandler {
|
||||
// })
|
||||
// .unwrap();
|
||||
|
||||
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;
|
||||
determine_tank_state(&mut board);
|
||||
//should be multsampled
|
||||
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(
|
||||
&board.board_hal.get_config().tank,
|
||||
&water_temp,
|
||||
))?))
|
||||
}
|
||||
|
||||
async fn write_time<T, const N: usize>(
|
||||
request: &mut Connection<'_, T, N>,
|
||||
) -> Result<Option<String>, anyhow::Error>
|
||||
) -> FatResult<Option<String>>
|
||||
where
|
||||
T: Read + Write
|
||||
T: Read + Write,
|
||||
{
|
||||
let actual_data = read_up_to_bytes_from_request(request, None).await?;
|
||||
let time: SetTime = serde_json::from_slice(&actual_data)?;
|
||||
let parsed = DateTime::parse_from_rfc3339(time.time).unwrap();
|
||||
esp_set_time(parsed).await;
|
||||
anyhow::Ok(None)
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
|
||||
async fn set_config<T, const N: usize>(
|
||||
request: &mut Connection<'_, T, N>,
|
||||
) -> Result<Option<String>, anyhow::Error>
|
||||
) -> FatResult<Option<String>>
|
||||
where
|
||||
T: Read + Write,
|
||||
{
|
||||
@@ -582,13 +598,13 @@ where
|
||||
board.board_hal.get_esp().save_config(all).await?;
|
||||
log::info!("Wrote config config {:?} with size {}", config, length);
|
||||
board.board_hal.set_config(config);
|
||||
anyhow::Ok(Some("saved".to_string()))
|
||||
Ok(Some("saved".to_string()))
|
||||
}
|
||||
|
||||
async fn read_up_to_bytes_from_request<T, const N: usize>(
|
||||
request: &mut Connection<'_, T, N>,
|
||||
limit: Option<usize>,
|
||||
) -> Result<Vec<u8>, anyhow::Error>
|
||||
) -> FatResult<Vec<u8>>
|
||||
where
|
||||
T: Read + Write,
|
||||
{
|
||||
@@ -597,10 +613,7 @@ where
|
||||
let mut total_read = 0;
|
||||
loop {
|
||||
let mut buf = [0_u8; 64];
|
||||
let read = match request.read(&mut buf).await {
|
||||
Ok(read) => read,
|
||||
Err(e) => bail!("Error reading request {:?}", e),
|
||||
};
|
||||
let read = request.read(&mut buf).await?;
|
||||
if read == 0 {
|
||||
break;
|
||||
}
|
||||
@@ -618,7 +631,7 @@ where
|
||||
|
||||
async fn wifi_scan<T, const N: usize>(
|
||||
_request: &mut Connection<'_, T, N>,
|
||||
) -> Result<Option<String>, anyhow::Error> {
|
||||
) -> FatResult<Option<String>> {
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
info!("start wifi scan");
|
||||
//let scan_result = board.board_hal.get_esp().wifi_scan().await?
|
||||
@@ -629,93 +642,87 @@ async fn wifi_scan<T, const N: usize>(
|
||||
//.for_each(|s| ssids.push(s.ssid.to_string()));
|
||||
let ssid_json = serde_json::to_string(&SSIDList { ssids })?;
|
||||
info!("Sending ssid list {}", &ssid_json);
|
||||
anyhow::Ok(Some(ssid_json))
|
||||
Ok(Some(ssid_json))
|
||||
}
|
||||
|
||||
async fn get_log<T, const N: usize>(
|
||||
conn: &mut Connection<'_, T, N>,
|
||||
) -> anyhow::Result<()>
|
||||
async fn get_log<T, const N: usize>(conn: &mut Connection<'_, T, N>) -> FatResult<()>
|
||||
where
|
||||
T: Read + Write,{
|
||||
T: Read + Write,
|
||||
{
|
||||
let log = LOG_ACCESS.lock().await.get();
|
||||
conn.initiate_response(
|
||||
200,
|
||||
Some("OK"),
|
||||
&[("Content-Type", "text/javascript")],
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
conn.write_all("[".as_bytes()).await.unwrap();
|
||||
conn.initiate_response(200, Some("OK"), &[("Content-Type", "text/javascript")])
|
||||
.await?;
|
||||
conn.write_all("[".as_bytes()).await?;
|
||||
let mut append = false;
|
||||
for entry in log {
|
||||
for entry in log {
|
||||
if append {
|
||||
conn.write_all(",".as_bytes()).await.unwrap();
|
||||
conn.write_all(",".as_bytes()).await?;
|
||||
}
|
||||
append = true;
|
||||
let json = serde_json::to_string(&entry)?;
|
||||
conn.write_all(json.as_bytes()).await.unwrap();
|
||||
conn.write_all(json.as_bytes()).await?;
|
||||
}
|
||||
conn.write_all("]".as_bytes()).await.unwrap();
|
||||
conn.write_all("]".as_bytes()).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_log_localization_config<T, const N: usize>(
|
||||
_request: &mut Connection<'_, T, N>,
|
||||
) -> Result<Option<String>, anyhow::Error> {
|
||||
anyhow::Ok(Some(serde_json::to_string(
|
||||
) -> FatResult<Option<String>> {
|
||||
Ok(Some(serde_json::to_string(
|
||||
&LogMessage::to_log_localisation_config(),
|
||||
)?))
|
||||
}
|
||||
async fn list_files<T, const N: usize>(
|
||||
_request: &mut Connection<'_, T, N>,
|
||||
) -> Result<Option<String>, anyhow::Error> {
|
||||
) -> FatResult<Option<String>> {
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
let result = board.board_hal.get_esp().list_files().await?;
|
||||
let file_list_json = serde_json::to_string(&result)?;
|
||||
anyhow::Ok(Some(file_list_json))
|
||||
Ok(Some(file_list_json))
|
||||
}
|
||||
async fn get_config<T, const N: usize>(
|
||||
_request: &mut Connection<'_, T, N>,
|
||||
) -> Result<Option<String>, anyhow::Error> {
|
||||
) -> FatResult<Option<String>> {
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
let json = serde_json::to_string(&board.board_hal.get_config())?;
|
||||
anyhow::Ok(Some(json))
|
||||
Ok(Some(json))
|
||||
}
|
||||
|
||||
async fn get_solar_state<T, const N: usize>(
|
||||
_request: &mut Connection<'_, T, N>,
|
||||
) -> Result<Option<String>, anyhow::Error> {
|
||||
) -> FatResult<Option<String>> {
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
let state = SolarState {
|
||||
mppt_voltage: board.board_hal.get_mptt_voltage().await?.as_millivolts() as f32,
|
||||
mppt_current: board.board_hal.get_mptt_current().await?.as_milliamperes() as f32,
|
||||
is_day: board.board_hal.is_day(),
|
||||
};
|
||||
anyhow::Ok(Some(serde_json::to_string(&state)?))
|
||||
Ok(Some(serde_json::to_string(&state)?))
|
||||
}
|
||||
|
||||
async fn get_battery_state<T, const N: usize>(
|
||||
_request: &mut Connection<'_, T, N>,
|
||||
) -> Result<Option<String>, anyhow::Error> {
|
||||
) -> FatResult<Option<String>> {
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
let battery_state = board
|
||||
.board_hal
|
||||
.get_battery_monitor()
|
||||
.get_battery_state()
|
||||
.await?;
|
||||
anyhow::Ok(Some(serde_json::to_string(&battery_state)?))
|
||||
Ok(Some(serde_json::to_string(&battery_state)?))
|
||||
}
|
||||
|
||||
async fn get_version_web<T, const N: usize>(
|
||||
_request: &mut Connection<'_, T, N>,
|
||||
) -> Result<Option<String>, anyhow::Error> {
|
||||
) -> FatResult<Option<String>> {
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
anyhow::Ok(Some(serde_json::to_string(&get_version(&mut board).await)?))
|
||||
Ok(Some(serde_json::to_string(&get_version(&mut board).await)?))
|
||||
}
|
||||
|
||||
async fn get_time<T, const N: usize>(
|
||||
_request: &mut Connection<'_, T, N>,
|
||||
) -> Result<Option<String>, anyhow::Error> {
|
||||
) -> FatResult<Option<String>> {
|
||||
let mut board = BOARD_ACCESS.get().await.lock().await;
|
||||
//TODO do not fail if rtc module is missing
|
||||
let native = esp_time().await.to_rfc3339();
|
||||
@@ -733,7 +740,7 @@ async fn get_time<T, const N: usize>(
|
||||
};
|
||||
let json = serde_json::to_string(&data)?;
|
||||
|
||||
anyhow::Ok(Some(json))
|
||||
Ok(Some(json))
|
||||
}
|
||||
|
||||
#[embassy_executor::task]
|
||||
@@ -943,8 +950,8 @@ pub async fn httpd(reboot_now: Arc<AtomicBool>, stack: Stack<'static>) {
|
||||
|
||||
async fn handle_json<'a, T, const N: usize>(
|
||||
conn: &mut Connection<'a, T, N>,
|
||||
chain: anyhow::Result<Option<String>>,
|
||||
) -> anyhow::Result<u32, Error<T::Error>>
|
||||
chain: FatResult<Option<String>>,
|
||||
) -> FatResult<u32>
|
||||
where
|
||||
T: Read + Write,
|
||||
<T as embedded_io_async::ErrorType>::Error: Debug,
|
||||
|
||||
Reference in New Issue
Block a user