Compare commits

...

5 Commits

Author SHA1 Message Date
252e63c607 fixed RFID reader outputting un-aligned IDs in buffer 2025-10-11 14:48:01 +02:00
99848f0e6d added TryFrom<[u8;12]> to TallyID 2025-10-11 14:47:29 +02:00
f46cdc4d29 implemented Display for TallyID 2025-10-11 14:31:26 +02:00
a8d64f6af5 fixed list_day for sd_card 2025-10-11 14:16:28 +02:00
8fb6bac651 added Ord to Day 2025-10-11 14:16:12 +02:00
4 changed files with 64 additions and 10 deletions

View File

@@ -1,6 +1,6 @@
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use esp_hal::{Async, uart::Uart}; use esp_hal::{Async, uart::Uart};
use log::{debug, info}; use log::{debug, info, warn};
use crate::TallyPublisher; use crate::TallyPublisher;
@@ -18,10 +18,14 @@ pub async fn rfid_reader_task(mut uart_device: Uart<'static, Async>, chan: Tally
} }
info!("Read {n} bytes from UART: {hex_str}"); info!("Read {n} bytes from UART: {hex_str}");
// The first byte is always 0x02 (Start of text) match extract_id(&uart_buffer) {
// Followed by 12 Bytes of chars Some(read) => {
// Ended by 0x03 (End of text) chan.publish(read.try_into().unwrap()).await;
chan.publish(uart_buffer[1..13].try_into().unwrap()).await; }
None => {
warn!("Invalid read from the RFID reader");
}
};
} }
Err(e) => { Err(e) => {
log::error!("Error reading from UART: {e}"); log::error!("Error reading from UART: {e}");
@@ -30,3 +34,35 @@ pub async fn rfid_reader_task(mut uart_device: Uart<'static, Async>, chan: Tally
Timer::after(Duration::from_millis(200)).await; Timer::after(Duration::from_millis(200)).await;
} }
} }
/// Scans the UART output and retuns the first propper read ID
/// This ensures that only valid ID are parsed
///
/// A valid read looks like this:
/// The first byte is always 0x02 (Start of text)
/// Followed by 12 Bytes of chars
/// Ended by 0x03 (End of text)
pub fn extract_id(buffer: &[u8]) -> Option<[u8; 12]> {
const STX: u8 = 0x02; // Start of Text ASCII char
const ETX: u8 = 0x03; // End of Text ASCII char
const ID_LENGTH: usize = 12;
const MINIMUM_SEQUENCE: usize = ID_LENGTH + 2; // STX + 12 bytes + ETX
if buffer.len() < MINIMUM_SEQUENCE {
return None;
}
for window_start in 0..=buffer.len() - MINIMUM_SEQUENCE {
if buffer[window_start] == STX {
let id_end = window_start + ID_LENGTH + 1;
if buffer[id_end] == ETX {
let mut id = [0u8; ID_LENGTH];
id.copy_from_slice(&buffer[window_start + 1..id_end]);
return Some(id);
}
}
}
None
}

View File

@@ -132,14 +132,17 @@ impl Persistence for SDCardPersistence {
async fn list_days(&mut self) -> Vec<Day> { async fn list_days(&mut self) -> Vec<Day> {
let mut vol_0 = self.vol_mgr.open_volume(VolumeIdx(0)).unwrap(); let mut vol_0 = self.vol_mgr.open_volume(VolumeIdx(0)).unwrap();
let mut root_dir = vol_0.open_root_dir().unwrap(); let mut root_dir = vol_0.open_root_dir().unwrap();
let mut days_dir = root_dir.open_dir("days").unwrap();
let mut days_dir = root_dir.open_dir(".").unwrap();
let mut days: Vec<Day> = Vec::new(); let mut days: Vec<Day> = Vec::new();
days_dir days_dir
.iterate_dir(|e| { .iterate_dir(|e| {
let filename = e.name.clone(); let filename = e.name.clone();
let day: Day = filename.try_into().unwrap();
days.push(day); if let Ok(day) = filename.try_into() {
days.push(day);
}
}) })
.unwrap(); .unwrap();

View File

@@ -3,7 +3,7 @@ use core::fmt::Write;
use embedded_sdmmc::ShortFileName; use embedded_sdmmc::ShortFileName;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Day(u32); pub struct Day(u32);
impl Day { impl Day {

View File

@@ -1,4 +1,4 @@
use core::str::FromStr; use core::{fmt::Display, str::FromStr};
use serde::{Deserialize, Deserializer, Serialize, Serializer, de}; use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
@@ -72,6 +72,21 @@ impl TryFrom<&[u8]> for TallyID {
} }
} }
impl TryFrom<[u8; 12]> for TallyID {
type Error = ();
fn try_from(value: [u8; 12]) -> Result<Self, Self::Error> {
Self::try_from(&value as &[u8])
}
}
impl Display for TallyID {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let s: heapless::String<12> = (*self).into();
write!(f, "{}", s)
}
}
impl Serialize for TallyID { impl Serialize for TallyID {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where where