Add some error handling

This commit is contained in:
2023-11-19 20:28:55 +01:00
parent 56ee85b677
commit e0315538a3
4 changed files with 51 additions and 14 deletions

7
Cargo.lock generated
View File

@@ -47,6 +47,12 @@ dependencies = [
"memchr",
]
[[package]]
name = "anyhow"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]]
name = "async-trait"
version = "0.1.74"
@@ -171,6 +177,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
name = "elwa-dc"
version = "0.1.0"
dependencies = [
"anyhow",
"axum",
"base64",
"log",

View File

@@ -7,6 +7,7 @@ edition = "2021"
dummy = []
[dependencies]
anyhow = "1.0.75"
axum = "0.6.20"
base64 = "0.21.5"
log = "0.4.20"

View File

@@ -29,7 +29,7 @@
<h2>Zustand</h2>
<p>Isolationsmessung: {11}</p>
<p>Gerätetemperatur: {12}</p>
<p>Gerätetemperatur: {12} °C</p>
<p>Status: {13}</p>
<p>DC Trenner: {14}</p>
<p>DC Relais: {15}</p>

View File

@@ -1,4 +1,10 @@
use axum::{response::Html, routing::get, Router};
use anyhow::Context;
use axum::{
http::StatusCode,
response::{Html, IntoResponse, Response},
routing::get,
Router,
};
use strum::{EnumIter, IntoEnumIterator};
#[derive(EnumIter, Debug)]
@@ -68,6 +74,27 @@ struct Status<'a> {
seriennummer: &'a str,
}
struct AppError(anyhow::Error);
impl IntoResponse for AppError {
fn into_response(self) -> Response {
(
StatusCode::INTERNAL_SERVER_ERROR,
format!("Internal Server Error:\n{:?}", self.0),
)
.into_response()
}
}
impl<E> From<E> for AppError
where
E: Into<anyhow::Error>,
{
fn from(err: E) -> Self {
Self(err.into())
}
}
#[tokio::main]
async fn main() {
let app = Router::new().route("/", get(handler));
@@ -78,10 +105,10 @@ async fn main() {
.unwrap();
}
async fn handler() -> Html<String> {
async fn handler() -> Result<Html<String>, AppError> {
log::info!("Fetch new data");
let data = read_device();
let data = read_device().context("Could not retrieve device data")?;
let data_string = std::str::from_utf8(&data).unwrap();
let mut status = Status::default();
@@ -127,7 +154,7 @@ async fn handler() -> Html<String> {
}
}
Html(format!(
Ok(Html(format!(
include_str!("index.html"),
status.wassertemp,
status.wassertemp_min,
@@ -149,32 +176,34 @@ async fn handler() -> Html<String> {
status.betriebstag,
status.firmware,
status.seriennummer,
))
)))
}
#[cfg(not(feature = "dummy"))]
fn read_device() -> Vec<u8> {
fn read_device() -> anyhow::Result<Vec<u8>> {
use std::io::{BufRead, BufReader};
use std::time::Duration;
let mut port = serialport::new("/dev/ttyUSB0", 9600)
.timeout(Duration::from_secs(5))
.timeout(Duration::from_millis(100))
.open()
.expect("Failed to open port");
.context("Could not open serial device port")?;
write!(&mut port, "rs\r\n").expect("Write failed!");
write!(&mut port, "rs\r\n").context("Could not write to serial connection")?;
let mut reader = BufReader::new(port);
let mut data: Vec<u8> = Vec::new();
reader.read_until(b'\n', &mut data).expect("Found no data!");
reader
.read_until(b'\n', &mut data)
.context("Could not read from serial connection")?;
data
Ok(data)
}
#[cfg(feature = "dummy")]
fn read_device() -> Vec<u8> {
fn read_device() -> anyhow::Result<Vec<u8>> {
use base64::{engine::general_purpose, Engine as _};
const SAMPLE_OUTPUT: &str = "ZHIJVjEuMzEJMzUJMTIJMQkxCTEJMjM1CTE3NQkyNDUJNzU5CTY1MAkyNQk5MAkxODkuNQkxOTAuMDMJMS4xNDM1CTIxNy4yOQk3NzgJOTE3MjUJMAktNwk3LjkJNTI1CTM2OAkzNTgJMjQwCTEJMTIwMTAwMjMwMjEwMDAyMwk3NTkJNg0K";
general_purpose::STANDARD.decode(SAMPLE_OUTPUT).unwrap()
Ok(general_purpose::STANDARD.decode(SAMPLE_OUTPUT)?)
}