implement card storing

This commit is contained in:
2026-08-26 19:56:29 +00:00
parent ce5183da38
commit 67bf3ddadb
4 changed files with 59 additions and 20 deletions
+3 -3
View File
@@ -1,14 +1,14 @@
use core::fmt::Display; use core::fmt::Display;
use crate::card::model::NfcPayload; use crate::card::model::RawCard;
use alloc::string::{String, ToString}; use alloc::string::{String, ToString};
pub fn split_nfc_hex(payload: &[u8]) -> Option<NfcPayload> { pub fn split_nfc_hex(payload: &[u8]) -> Option<RawCard> {
if payload.len() < 0x35A { if payload.len() < 0x35A {
return None; return None;
} }
Some(NfcPayload { Some(RawCard {
event_encoding: payload[0..2].try_into().ok()?, event_encoding: payload[0..2].try_into().ok()?,
card_type: payload[2], card_type: payload[2],
card_uuid: payload[3..5].try_into().ok()?, card_uuid: payload[3..5].try_into().ok()?,
+3 -3
View File
@@ -10,7 +10,7 @@ use binary_serde::BinarySerde;
#[derive(Debug, BinarySerde, PartialEq, Eq, Clone, Copy)] #[derive(Debug, BinarySerde, PartialEq, Eq, Clone, Copy)]
#[repr(C)] #[repr(C)]
pub struct NfcPayload { pub struct RawCard {
pub event_encoding: [u8; 2], pub event_encoding: [u8; 2],
pub card_type: u8, pub card_type: u8,
pub card_uuid: [u8; 2], pub card_uuid: [u8; 2],
@@ -238,10 +238,10 @@ pub struct Card {
pub sprite: Sprite, pub sprite: Sprite,
} }
impl<'a> TryFrom<NfcPayload> for Card { impl<'a> TryFrom<RawCard> for Card {
type Error = &'static str; type Error = &'static str;
fn try_from(payload: NfcPayload) -> Result<Self, Self::Error> { fn try_from(payload: RawCard) -> Result<Self, Self::Error> {
let uuid: String = "empty for now".into(); //str::from_utf8(payload.card_uuid).unwrap().into(); let uuid: String = "empty for now".into(); //str::from_utf8(payload.card_uuid).unwrap().into();
let event = decode_known_event(&payload.event_encoding); let event = decode_known_event(&payload.event_encoding);
let cardtype = CardType::from(payload.card_type); let cardtype = CardType::from(payload.card_type);
+49 -14
View File
@@ -3,9 +3,9 @@ use alloc::vec::Vec;
use binary_serde::{BinarySerde, Endianness, DeserializeError}; use binary_serde::{BinarySerde, Endianness, DeserializeError};
//use crate::card::model::NfcPayload; //use crate::card::model::Nfcraw_card;
use crate::card::model::NfcPayload; use crate::card::model::RawCard;
use crate::storage::store::{Store, StoreError}; use crate::storage::store::{Store, StoreError};
use crate::storage::{MemoryRegion,CARDSTORE_REGION}; use crate::storage::{MemoryRegion,CARDSTORE_REGION};
@@ -14,16 +14,20 @@ const MAX_CARDS: usize = 20000;
const COUNT_REGION: MemoryRegion = MemoryRegion { offset: CARDSTORE_REGION.offset, size: size_of::<u32>()}; const COUNT_REGION: MemoryRegion = MemoryRegion { offset: CARDSTORE_REGION.offset, size: size_of::<u32>()};
#[derive(Debug, BinarySerde, Default, PartialEq, Eq)] #[derive(Debug, BinarySerde, PartialEq, Eq, Clone)]
#[repr(C)] #[repr(C)]
pub struct AllocationTableEntry { pub struct AllocationTableEntry {
uuid: u32, uuid: u32,
// this is the numeric offset of the AllocationTableEntry
// as well as the card entry in flash memory
// size_of::<AllocationTableEntry>() * offset
// size_of::<RawCard>() * offset
offset: u32, offset: u32,
creation_date: u64, creation_date: u64,
last_read_date: u64, last_read_date: u64,
// how often a card has been read // how often a card has been read by nfc
read_count: u32, read_count: u32,
deleted: bool, deleted: bool,
@@ -31,9 +35,16 @@ pub struct AllocationTableEntry {
reserved: [u64; 4], reserved: [u64; 4],
} }
const ALLOCATION_TABLE_SIZE: usize = size_of::<AllocationTableEntry>(); impl AllocationTableEntry {
fn new(uuid: u32, offset: u32, timestamp: u64) -> Self {
Self {
uuid, offset, creation_date: timestamp, last_read_date: timestamp, read_count: 0, deleted: true, reserved: [0; 4]
}
}
}
const ALLOCATION_TABLE_REGION: MemoryRegion = MemoryRegion {offset: COUNT_REGION.end() as u32, size: MAX_CARDS * size_of::<AllocationTableEntry>()};
const ALLOCATION_TABLE_REGION: MemoryRegion = MemoryRegion {offset: COUNT_REGION.end() as u32, size: MAX_CARDS * AllocationTableEntry::SERIALIZED_SIZE};
const CARDS_REGION: MemoryRegion = MemoryRegion { offset: ALLOCATION_TABLE_REGION.end() as u32, size: CARDSTORE_REGION.size - ALLOCATION_TABLE_REGION.end()}; const CARDS_REGION: MemoryRegion = MemoryRegion { offset: ALLOCATION_TABLE_REGION.end() as u32, size: CARDSTORE_REGION.size - ALLOCATION_TABLE_REGION.end()};
@@ -58,7 +69,7 @@ impl From<DeserializeError> for CardStoreError {
pub struct CardStore { pub struct CardStore {
store: Store, store: Store,
count: usize, count: u32,
pub allocation_table: BTreeMap<u32, AllocationTableEntry> pub allocation_table: BTreeMap<u32, AllocationTableEntry>
} }
@@ -68,14 +79,14 @@ impl CardStore {
store.read(COUNT_REGION.offset, &mut count_bytes)?; store.read(COUNT_REGION.offset, &mut count_bytes)?;
let count: usize = usize::from_ne_bytes(count_bytes); let count: u32 = u32::from_ne_bytes(count_bytes);
let mut allocation_table_entries: Vec<u8> = Vec::with_capacity(ALLOCATION_TABLE_SIZE * count); let mut allocation_table_entries: Vec<u8> = Vec::with_capacity(AllocationTableEntry::SERIALIZED_SIZE * count as usize);
store store
.read(ALLOCATION_TABLE_REGION.offset, &mut allocation_table_entries)?; .read(ALLOCATION_TABLE_REGION.offset, &mut allocation_table_entries)?;
let chunks = allocation_table_entries.into_chunks::<ALLOCATION_TABLE_SIZE>(); let chunks = allocation_table_entries.into_chunks::<{ AllocationTableEntry::SERIALIZED_SIZE }>();
let mut allocation_table = BTreeMap::<u32, AllocationTableEntry>::new(); let mut allocation_table = BTreeMap::<u32, AllocationTableEntry>::new();
for chunk in chunks { for chunk in chunks {
@@ -86,13 +97,37 @@ impl CardStore {
Ok(Self { store, count, allocation_table }) Ok(Self { store, count, allocation_table })
} }
pub fn get_card_by_uuid(&mut self, uuid: u32) -> Result<NfcPayload, CardStoreError> { pub fn get_card_by_uuid(&mut self, uuid: u32) -> Result<RawCard, CardStoreError> {
let entry = self.allocation_table.get(&uuid).ok_or(CardStoreError::NoEntry)?; let entry = self.allocation_table.get(&uuid).ok_or(CardStoreError::NoEntry)?;
let mut payload: [u8; size_of::<NfcPayload>()] = [0; size_of::<NfcPayload>()]; let mut raw_card: [u8; size_of::<RawCard>()] = [0; size_of::<RawCard>()];
self.store.read(entry.offset, &mut payload)?; self.store.read(entry.offset, &mut raw_card)?;
Ok(NfcPayload::binary_deserialize(payload.as_ref(), Endianness::Little)?) Ok(RawCard::binary_deserialize(raw_card.as_ref(), Endianness::Little)?)
} }
pub fn save_raw_card(&mut self, raw_card: RawCard, timestamp: u64) -> Result<(), CardStoreError> {
let uuid: u32 = (u16::from_ne_bytes(raw_card.event_encoding) as u32) << 16 | (u16::from_ne_bytes(raw_card.card_uuid) as u32);
let entry = match self.allocation_table.values_mut().find(|entry| entry.deleted) {
Some(entry) => entry,
None => {
let entry = AllocationTableEntry::new(uuid, self.count + 1, timestamp);
self.allocation_table.insert(uuid, entry);
self.allocation_table.get_mut(&uuid).expect("entry was just inserted")
}
};
entry.deleted = false;
let mut serialized_card: [u8; RawCard::SERIALIZED_SIZE] = [0; RawCard::SERIALIZED_SIZE];
raw_card.binary_serialize(&mut serialized_card, Endianness::Little);
self.store.write(CARDS_REGION.offset + entry.offset * RawCard::SERIALIZED_SIZE as u32, &mut serialized_card)?;
let mut serialized_entry: [u8; AllocationTableEntry::SERIALIZED_SIZE] = [0; AllocationTableEntry::SERIALIZED_SIZE];
entry.binary_serialize(&mut serialized_entry, Endianness::Little);
self.store.write(ALLOCATION_TABLE_REGION.offset + entry.offset * AllocationTableEntry::SERIALIZED_SIZE as u32, &mut serialized_entry)?;
self.count += 1;
Ok(())
}
} }
+4
View File
@@ -37,4 +37,8 @@ impl Store {
pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), StoreError> { pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), StoreError> {
self.storage.read(FLASH_ADDR + offset, bytes) self.storage.read(FLASH_ADDR + offset, bytes)
} }
pub fn write(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), StoreError> {
self.storage.write(FLASH_ADDR + offset, bytes)
}
} }