diff --git a/firmware/Cargo.lock b/firmware/Cargo.lock index 229b906..231ea32 100644 --- a/firmware/Cargo.lock +++ b/firmware/Cargo.lock @@ -1931,6 +1931,7 @@ dependencies = [ name = "touch-n-drink" version = "0.0.0" dependencies = [ + "chrono", "display-interface", "embassy-embedded-hal", "embassy-executor", diff --git a/firmware/Cargo.toml b/firmware/Cargo.toml index 92fea88..d579b32 100644 --- a/firmware/Cargo.toml +++ b/firmware/Cargo.toml @@ -44,6 +44,7 @@ overflow-checks = false git2 = { version = "0.19", default-features = false } [dependencies] +chrono = { version = "0.4", default-features = false, features = ["alloc"] } display-interface = "0.5" embassy-embedded-hal = "0.2" embassy-executor = "0.6" diff --git a/firmware/src/http.rs b/firmware/src/http.rs index 741f9d3..9cf9d4e 100644 --- a/firmware/src/http.rs +++ b/firmware/src/http.rs @@ -1,8 +1,10 @@ use crate::json::{self, FromJson, ToJson}; +use crate::time; use crate::wifi::{DnsSocket, TcpClient, TcpConnection, Wifi}; use alloc::vec::Vec; +use chrono::{DateTime, Utc}; use core::convert::Infallible; -use core::fmt; +use core::{fmt, str}; use embedded_io_async::{BufRead, Read}; use log::debug; use reqwless::client::{HttpClient, HttpResource, HttpResourceRequestBuilder}; @@ -212,6 +214,18 @@ impl<'a> Connection<'a> { let response = request.send(rx_buf).await?; debug!("HTTP: Status {}", response.status.0); + // Extract current date and time from response + let time = response + .headers() + .find_map(|(k, v)| (k == "Date").then_some(v)) + .and_then(|v| str::from_utf8(v).ok()) + .and_then(|s| DateTime::parse_from_rfc2822(s).ok()) + .map(|d| d.with_timezone(&Utc)); + if let Some(time) = time { + time::set(time); + } + + // Check HTTP response status if response.status.0 == 401 { return Err(Error::Unauthorized); } else if response.status.is_server_error() { diff --git a/firmware/src/main.rs b/firmware/src/main.rs index f4a803b..bb69939 100644 --- a/firmware/src/main.rs +++ b/firmware/src/main.rs @@ -50,6 +50,7 @@ mod keypad; mod nfc; mod pn532; mod screen; +mod time; mod ui; mod user; mod vereinsflieger; diff --git a/firmware/src/time.rs b/firmware/src/time.rs new file mode 100644 index 0000000..2928c26 --- /dev/null +++ b/firmware/src/time.rs @@ -0,0 +1,44 @@ +use chrono::{DateTime, TimeDelta, Utc}; +use core::cell::RefCell; +use embassy_sync::blocking_mutex::CriticalSectionMutex; +use log::debug; + +/// Calculated time of system start +static SYSTEM_START_TIME: CriticalSectionMutex>>> = + CriticalSectionMutex::new(RefCell::new(None)); + +/// Time of system start +fn start_time() -> Option> { + SYSTEM_START_TIME.lock(|sst| *sst.borrow()) +} + +/// Set time of system start +fn set_start_time(time: DateTime) { + SYSTEM_START_TIME.lock(|sst| { + *sst.borrow_mut() = Some(time); + }); +} + +/// Duration of system run time +pub fn uptime() -> Option { + let millis = esp_hal::time::now().duration_since_epoch().to_millis(); + TimeDelta::try_milliseconds(i64::try_from(millis).ok()?) +} + +/// Current time +#[allow(dead_code)] +pub fn now() -> Option> { + if let (Some(start_time), Some(uptime)) = (start_time(), uptime()) { + Some(start_time + uptime) + } else { + None + } +} + +/// Set current time by using the given current time to calculate the time of system start +pub fn set(now: DateTime) { + if let Some(uptime) = uptime() { + set_start_time(now - uptime); + debug!("Time: Current time set to {}", now); + } +}