diff --git a/Cargo.lock b/Cargo.lock
index 973f903..da8ed39 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
diff --git a/Cargo.toml b/Cargo.toml
index e0c5214..0721848 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
dummy = []
[dependencies]
+anyhow = "1.0.75"
axum = "0.6.20"
base64 = "0.21.5"
log = "0.4.20"
diff --git a/src/index.html b/src/index.html
index 518ecf1..37d3aee 100644
--- a/src/index.html
+++ b/src/index.html
@@ -29,7 +29,7 @@
Zustand
Isolationsmessung: {11}
- Gerätetemperatur: {12}
+ Gerätetemperatur: {12} °C
Status: {13}
DC Trenner: {14}
DC Relais: {15}
diff --git a/src/main.rs b/src/main.rs
index 582b75d..47b68b3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -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 From for AppError
+where
+ E: Into,
+{
+ 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 {
+async fn handler() -> Result, 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 {
}
}
- Html(format!(
+ Ok(Html(format!(
include_str!("index.html"),
status.wassertemp,
status.wassertemp_min,
@@ -149,32 +176,34 @@ async fn handler() -> Html {
status.betriebstag,
status.firmware,
status.seriennummer,
- ))
+ )))
}
#[cfg(not(feature = "dummy"))]
-fn read_device() -> Vec {
+fn read_device() -> anyhow::Result> {
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 = 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 {
+fn read_device() -> anyhow::Result> {
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)?)
}