From f1b471c6d85a6492c267b923112e880139113bfc Mon Sep 17 00:00:00 2001 From: Djeeberjr Date: Fri, 10 Oct 2025 01:12:46 +0200 Subject: [PATCH] changed Day implementation --- src/drivers/rtc.rs | 27 +---------------- src/init/sd_card.rs | 17 ++++++----- src/main.rs | 4 +-- src/store/day.rs | 63 ++++++++++++++++++++++++++++++++++++++++ src/store/id_store.rs | 10 +++---- src/store/mod.rs | 3 +- src/store/persistence.rs | 8 ++--- 7 files changed, 85 insertions(+), 47 deletions(-) create mode 100644 src/store/day.rs diff --git a/src/drivers/rtc.rs b/src/drivers/rtc.rs index bd3da9b..84ca3c5 100644 --- a/src/drivers/rtc.rs +++ b/src/drivers/rtc.rs @@ -9,7 +9,7 @@ use esp_hal::{ }; use log::{debug, error, info}; -use crate::{FEEDBACK_STATE, drivers, feedback, store::Date}; +use crate::{FEEDBACK_STATE, drivers, feedback}; include!(concat!(env!("OUT_DIR"), "/build_time.rs")); @@ -45,31 +45,6 @@ impl RTCClock { } } } - - pub async fn get_date(&mut self) -> Date { - let (year, month, day) = unix_to_ymd_string(self.get_time().await); - - let mut buffer: Date = [0; 10]; - - // Write YYYY - buffer[0] = b'0' + ((year / 1000) % 10) as u8; - buffer[1] = b'0' + ((year / 100) % 10) as u8; - buffer[2] = b'0' + ((year / 10) % 10) as u8; - buffer[3] = b'0' + (year % 10) as u8; - buffer[4] = b'.'; - - // Write MM - buffer[5] = b'0' + (month / 10) as u8; - buffer[6] = b'0' + (month % 10) as u8; - - buffer[7] = b'.'; - - // Write DD - buffer[8] = b'0' + (day / 10) as u8; - buffer[9] = b'0' + (day % 10) as u8; - - buffer - } } fn unix_to_ymd_string(timestamp: u64) -> (u16, u8, u8) { diff --git a/src/init/sd_card.rs b/src/init/sd_card.rs index 23f6bd7..48cc284 100644 --- a/src/init/sd_card.rs +++ b/src/init/sd_card.rs @@ -4,7 +4,7 @@ use embedded_hal_bus::spi::ExclusiveDevice; use embedded_sdmmc::{SdCard, TimeSource, Timestamp, VolumeIdx, VolumeManager}; use esp_hal::{Blocking, gpio::Output, spi::master::Spi}; -use crate::store::{AttendanceDay, Date, persistence::Persistence}; +use crate::store::{AttendanceDay, day::Day, persistence::Persistence}; pub struct DummyTimesource; @@ -39,7 +39,7 @@ pub struct SDCardPersistence { } impl Persistence for SDCardPersistence { - async fn load_day(&mut self, day: crate::store::Date) -> Option { + async fn load_day(&mut self, day: Day) -> Option { let mut vol_0 = self.vol_mgr.open_volume(VolumeIdx(0)).unwrap(); let mut root_dir = vol_0.open_root_dir().unwrap(); let mut file = root_dir.open_file_in_dir("day.jsn", embedded_sdmmc::Mode::ReadOnly); @@ -53,12 +53,13 @@ impl Persistence for SDCardPersistence { let read = open_file.read(&mut read_buffer).unwrap(); open_file.close().unwrap(); - let day: AttendanceDay = serde_json::from_slice(&read_buffer[..read]).unwrap(); + // let day: AttendanceDay = serde_json::from_slice(&read_buffer[..read]).unwrap(); - Some(day) + // Some(day) + None } - async fn save_day(&mut self, day: Date, data: &AttendanceDay) { + async fn save_day(&mut self, day: Day, data: &AttendanceDay) { let mut vol_0 = self.vol_mgr.open_volume(VolumeIdx(0)).unwrap(); let mut root_dir = vol_0.open_root_dir().unwrap(); @@ -78,15 +79,15 @@ impl Persistence for SDCardPersistence { todo!() } - async fn list_days(&mut self) -> Vec { + async fn list_days(&mut self) -> Vec { let mut vol_0 = self.vol_mgr.open_volume(VolumeIdx(0)).unwrap(); let mut root_dir = vol_0.open_root_dir().unwrap(); let mut days_dir = root_dir.open_dir("days").unwrap(); - let mut days: Vec<[u8; 10]> = Vec::new(); + let mut days: Vec = Vec::new(); days_dir .iterate_dir(|e| { - days.push([0; 10]); + days.push(Day::new(0)); }) .unwrap(); diff --git a/src/main.rs b/src/main.rs index c39bd30..a9adcd4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,7 +25,7 @@ extern crate alloc; use crate::{ init::sd_card::SDCardPersistence, - store::{Date, IDStore, tally_id::TallyID}, + store::{IDStore, day::Day, tally_id::TallyID}, webserver::start_webserver, }; @@ -86,7 +86,7 @@ async fn main(mut spawner: Spawner) { Message(msg) => { debug!("Got message: {msg:?}"); - let day: Date = rtc.get_date().await; + let day: Day = rtc.get_time().await.into(); let added = shared_store.lock().await.add_id(msg, day).await; if added { diff --git a/src/store/day.rs b/src/store/day.rs new file mode 100644 index 0000000..b60f031 --- /dev/null +++ b/src/store/day.rs @@ -0,0 +1,63 @@ +use core::fmt::Write; + +use embedded_sdmmc::ShortFileName; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)] +pub struct Day(u32); + +impl Day { + const SECONDS_PER_DAY: u64 = 86_400; + + pub fn new(daystamp: u32) -> Self { + Day(daystamp) + } + + pub fn new_from_timestamp(time: u64) -> Self { + let day = time / Self::SECONDS_PER_DAY; + + if day > u32::MAX as u64 { + // TBH this would only happen if about 11 million years have passed + // I sure hope i don't have to work on this project any more then + // So we just cap it at this + Day(u32::MAX) + } else { + Day(day as u32) + } + } + + pub fn to_timestamp(self) -> u64 { + (self.0 as u64) * Self::SECONDS_PER_DAY + } + + pub fn to_string(self) -> heapless::String<8> { + let mut s: heapless::String<8> = heapless::String::new(); + write!(s, "{:08X}", self.0).unwrap(); + s + } + + pub fn from_hex_str(s: &str) -> Result { + if s.len() > 8 { + return Err("hex string too long"); + } + + u32::from_str_radix(s, 16) + .map_err(|_| "invalid hex string") + .map(Day) + } +} + +impl From for Day { + fn from(value: u64) -> Self { + Self::new_from_timestamp(value) + } +} + +impl TryFrom for Day { + type Error = (); + + fn try_from(value: ShortFileName) -> Result { + let name = core::str::from_utf8(value.base_name()).map_err(|_| ())?; + Self::from_hex_str(name).map_err(|_| ()) + } +} diff --git a/src/store/id_store.rs b/src/store/id_store.rs index e8c675b..752379d 100644 --- a/src/store/id_store.rs +++ b/src/store/id_store.rs @@ -2,19 +2,19 @@ use alloc::vec::Vec; use serde::Deserialize; use serde::Serialize; -use super::Date; use super::IDMapping; +use crate::store::day::Day; use crate::store::persistence::Persistence; use crate::store::tally_id::TallyID; #[derive(Clone, Serialize, Deserialize, Debug)] pub struct AttendanceDay { - date: Date, + date: Day, ids: Vec, } impl AttendanceDay { - pub fn new(date: Date) -> Self { + pub fn new(date: Day) -> Self { Self { date, ids: Vec::new(), @@ -46,7 +46,7 @@ impl IDStore { // None => IDMapping::new(), // }; - let current_date: Date = [0; 10]; + let current_date: Day = Day::new(0); let day = persistence_layer .load_day(current_date) @@ -72,7 +72,7 @@ impl IDStore { /// Add a new id for the current day /// Returns false if ID is already present at the current day. - pub async fn add_id(&mut self, id: TallyID, current_date: Date) -> bool { + pub async fn add_id(&mut self, id: TallyID, current_date: Day) -> bool { if self.current_day.date == current_date { let changed = self.current_day.add_id(id); if changed { diff --git a/src/store/mod.rs b/src/store/mod.rs index ef7402a..37d5d94 100644 --- a/src/store/mod.rs +++ b/src/store/mod.rs @@ -5,6 +5,5 @@ mod id_mapping; pub mod persistence; mod id_store; pub mod tally_id; - -pub type Date = [u8; 10]; +pub mod day; diff --git a/src/store/persistence.rs b/src/store/persistence.rs index 30ece88..63de781 100644 --- a/src/store/persistence.rs +++ b/src/store/persistence.rs @@ -1,11 +1,11 @@ use alloc::vec::Vec; -use crate::store::{Date, IDMapping, id_store::AttendanceDay}; +use crate::store::{IDMapping, day::Day, id_store::AttendanceDay}; pub trait Persistence { - async fn load_day(&mut self, day: Date) -> Option; - async fn save_day(&mut self, day: Date, data: &AttendanceDay); - async fn list_days(&mut self) -> Vec; + async fn load_day(&mut self, day: Day) -> Option; + async fn save_day(&mut self, day: Day, data: &AttendanceDay); + async fn list_days(&mut self) -> Vec; async fn load_mapping(&mut self) -> Option; async fn save_mapping(&mut self, data: &IDMapping);