implement card storing
This commit is contained in:
+3
-3
@@ -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
@@ -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
@@ -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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user