mirror of
https://github.com/Djeeberjr/fw-anwesenheit.git
synced 2025-09-13 01:54:18 +00:00
implemented SD card abstraction & used it in IDStore
This commit is contained in:
parent
b031a47e85
commit
fe90ca9aa9
79
Cargo.lock
generated
79
Cargo.lock
generated
@ -312,7 +312,7 @@ dependencies = [
|
||||
"edge-nal",
|
||||
"edge-raw",
|
||||
"embassy-futures",
|
||||
"embassy-time",
|
||||
"embassy-time 0.4.0",
|
||||
"heapless",
|
||||
"log",
|
||||
"num_enum",
|
||||
@ -325,7 +325,7 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac19c3edcdad839c71cb919cd09a632d9915d630760b37f0b74290188c08f248"
|
||||
dependencies = [
|
||||
"embassy-time",
|
||||
"embassy-time 0.4.0",
|
||||
"embedded-io-async",
|
||||
]
|
||||
|
||||
@ -358,7 +358,7 @@ dependencies = [
|
||||
"embassy-embedded-hal 0.4.0",
|
||||
"embassy-futures",
|
||||
"embassy-sync 0.6.2",
|
||||
"embassy-time",
|
||||
"embassy-time 0.4.0",
|
||||
"embedded-hal 0.2.7",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-async",
|
||||
@ -375,7 +375,7 @@ checksum = "d1611b7a7ab5d1fbed84c338df26d56fd9bded58006ebb029075112ed2c5e039"
|
||||
dependencies = [
|
||||
"embassy-futures",
|
||||
"embassy-hal-internal",
|
||||
"embassy-sync 0.7.0",
|
||||
"embassy-sync 0.7.2",
|
||||
"embedded-hal 0.2.7",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-async",
|
||||
@ -409,9 +409,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "embassy-futures"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067"
|
||||
checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01"
|
||||
|
||||
[[package]]
|
||||
name = "embassy-hal-internal"
|
||||
@ -424,14 +424,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "embassy-net"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "940c4b9fe5c1375b09a0c6722c0100d6b2ed46a717a34f632f26e8d7327c4383"
|
||||
checksum = "0558a231a47e7d4a06a28b5278c92e860f1200f24821d2f365a2f40fe3f3c7b2"
|
||||
dependencies = [
|
||||
"document-features",
|
||||
"embassy-net-driver",
|
||||
"embassy-sync 0.6.2",
|
||||
"embassy-time",
|
||||
"embassy-sync 0.7.2",
|
||||
"embassy-time 0.5.0",
|
||||
"embedded-io-async",
|
||||
"embedded-nal-async",
|
||||
"heapless",
|
||||
@ -461,15 +461,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "embassy-sync"
|
||||
version = "0.7.0"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cef1a8a1ea892f9b656de0295532ac5d8067e9830d49ec75076291fd6066b136"
|
||||
checksum = "73974a3edbd0bd286759b3d483540f0ebef705919a5f56f4fc7709066f71689b"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"critical-section",
|
||||
"embedded-io-async",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"futures-util",
|
||||
"heapless",
|
||||
"log",
|
||||
]
|
||||
@ -492,10 +492,26 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embassy-time-driver"
|
||||
version = "0.2.0"
|
||||
name = "embassy-time"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d45f5d833b6d98bd2aab0c2de70b18bfaa10faf661a1578fd8e5dfb15eb7eba"
|
||||
checksum = "f4fa65b9284d974dad7a23bb72835c4ec85c0b540d86af7fc4098c88cff51d65"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"critical-section",
|
||||
"document-features",
|
||||
"embassy-time-driver",
|
||||
"embedded-hal 0.2.7",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-async",
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embassy-time-driver"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a0a244c7dc22c8d0289379c8d8830cae06bb93d8f990194d0de5efb3b5ae7ba6"
|
||||
dependencies = [
|
||||
"document-features",
|
||||
]
|
||||
@ -544,6 +560,16 @@ dependencies = [
|
||||
"embedded-hal 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-hal-bus"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "513e0b3a8fb7d3013a8ae17a834283f170deaf7d0eeab0a7c1a36ad4dd356d22"
|
||||
dependencies = [
|
||||
"critical-section",
|
||||
"embedded-hal 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-io"
|
||||
version = "0.6.1"
|
||||
@ -579,14 +605,13 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "embedded-sdmmc-dev"
|
||||
name = "embedded-sdmmc"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ceec3a654b00a4acf9e2788d72b66fc3ba86d91b834586a4ed576324e351e38b"
|
||||
checksum = "a1132a10f327a9dff9d0629124e8b26cb2b3a930ab3dfedbadd295c107955e92"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-io",
|
||||
"heapless",
|
||||
"log",
|
||||
]
|
||||
@ -747,7 +772,7 @@ dependencies = [
|
||||
"document-features",
|
||||
"embassy-executor",
|
||||
"embassy-sync 0.6.2",
|
||||
"embassy-time",
|
||||
"embassy-time 0.4.0",
|
||||
"embassy-time-driver",
|
||||
"embassy-time-queue-utils",
|
||||
"esp-config 0.5.0",
|
||||
@ -1046,12 +1071,13 @@ dependencies = [
|
||||
"edge-nal-embassy",
|
||||
"embassy-executor",
|
||||
"embassy-net",
|
||||
"embassy-sync 0.7.0",
|
||||
"embassy-time",
|
||||
"embassy-sync 0.7.2",
|
||||
"embassy-time 0.4.0",
|
||||
"embedded-hal 1.0.0",
|
||||
"embedded-hal-bus",
|
||||
"embedded-io",
|
||||
"embedded-io-async",
|
||||
"embedded-sdmmc-dev",
|
||||
"embedded-sdmmc",
|
||||
"esp-alloc",
|
||||
"esp-bootloader-esp-idf",
|
||||
"esp-hal",
|
||||
@ -1063,6 +1089,7 @@ dependencies = [
|
||||
"log",
|
||||
"picoserve",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"smart-leds",
|
||||
"smoltcp",
|
||||
"static_cell",
|
||||
@ -1395,7 +1422,7 @@ dependencies = [
|
||||
"const-sha1",
|
||||
"data-encoding",
|
||||
"embassy-net",
|
||||
"embassy-time",
|
||||
"embassy-time 0.5.0",
|
||||
"embedded-io-async",
|
||||
"futures-util",
|
||||
"heapless",
|
||||
@ -1644,9 +1671,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.142"
|
||||
version = "1.0.143"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
|
||||
checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
|
@ -63,10 +63,12 @@ embassy-sync = { version = "0.7.0", features = ["log"] }
|
||||
ds3231 = { version = "0.3.0", features = ["async", "temperature_f32"] }
|
||||
chrono = { version = "0.4.41", default-features = false }
|
||||
dir-embed = "0.3.0"
|
||||
embedded-sdmmc-dev = "0.8.2"
|
||||
esp-hal-smartled = { git = "https://github.com/esp-rs/esp-hal-community.git", package = "esp-hal-smartled", branch = "main", features = ["esp32c6"]}
|
||||
smart-leds = "0.4.0"
|
||||
serde = { version = "1.0.219", default-features = false, features = ["derive", "alloc"] }
|
||||
embedded-sdmmc = "0.8.0"
|
||||
embedded-hal-bus = "0.3.0"
|
||||
serde_json = { version = "1.0.143", default-features = false, features = ["alloc"]}
|
||||
|
||||
[profile.dev]
|
||||
# Rust debug is too slow.
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod hardware;
|
||||
pub mod network;
|
||||
pub mod wifi;
|
||||
pub mod sd_card;
|
||||
|
@ -1,18 +1,18 @@
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_net::Stack;
|
||||
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embedded_sdmmc_dev::SdCard;
|
||||
use esp_hal::i2c::master::Config;
|
||||
use esp_hal::peripherals::{
|
||||
self, GPIO0, GPIO1, GPIO2, GPIO10, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22,
|
||||
GPIO23, I2C0, RMT, SPI2, UART1,
|
||||
GPIO0, GPIO1, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23, I2C0, RMT, SPI2,
|
||||
UART1,
|
||||
};
|
||||
use esp_hal::rmt::{ConstChannelAccess, Rmt, Tx};
|
||||
use esp_hal::rmt::{ConstChannelAccess, Rmt};
|
||||
use esp_hal::spi::{
|
||||
Mode,
|
||||
master::{Config as Spi_config, Spi},
|
||||
};
|
||||
|
||||
use esp_hal::Blocking;
|
||||
use esp_hal::time::Rate;
|
||||
use esp_hal::timer::timg::TimerGroup;
|
||||
use esp_hal::{
|
||||
@ -23,19 +23,12 @@ use esp_hal::{
|
||||
timer::systimer::SystemTimer,
|
||||
uart::Uart,
|
||||
};
|
||||
|
||||
use esp_hal_smartled::{SmartLedsAdapterAsync, buffer_size_async};
|
||||
|
||||
use smart_leds::colors::{BLUE, GREEN, RED};
|
||||
use smart_leds::{
|
||||
RGB8, SmartLedsWriteAsync, brightness, gamma,
|
||||
hsv::{Hsv, hsv2rgb},
|
||||
};
|
||||
|
||||
use esp_println::logger::init_logger;
|
||||
use log::{debug, error};
|
||||
|
||||
use crate::init::network;
|
||||
use crate::init::sd_card::setup_sdcard;
|
||||
use crate::init::wifi;
|
||||
|
||||
/*************************************************
|
||||
@ -55,7 +48,7 @@ use crate::init::wifi;
|
||||
*
|
||||
*************************************************/
|
||||
|
||||
pub const NUM_LEDS: usize = 66;
|
||||
pub const NUM_LEDS: usize = 66;
|
||||
pub const LED_BUFFER_SIZE: usize = NUM_LEDS * 25;
|
||||
|
||||
#[panic_handler]
|
||||
@ -101,15 +94,20 @@ pub async fn hardware_init(
|
||||
|
||||
let i2c_device = setup_i2c(peripherals.I2C0, peripherals.GPIO22, peripherals.GPIO23);
|
||||
|
||||
let spi_device = setup_spi(
|
||||
let spi_bus = setup_spi(
|
||||
peripherals.SPI2,
|
||||
peripherals.GPIO19,
|
||||
peripherals.GPIO20,
|
||||
peripherals.GPIO18,
|
||||
peripherals.GPIO2,
|
||||
);
|
||||
|
||||
let sd_card = setup_sdcard(spi_device);
|
||||
let sd_cs_pin = Output::new(
|
||||
peripherals.GPIO2,
|
||||
esp_hal::gpio::Level::High,
|
||||
OutputConfig::default(),
|
||||
);
|
||||
|
||||
let vol_mgr = setup_sdcard(spi_bus, sd_cs_pin);
|
||||
|
||||
let buzzer_gpio = peripherals.GPIO21;
|
||||
|
||||
@ -124,8 +122,13 @@ pub async fn hardware_init(
|
||||
|
||||
// Initialize the level shifter for the NFC reader and LED (output-enable (OE) input is low, all outputs are placed in the high-impedance (Hi-Z) state)
|
||||
fn init_lvl_shifter(oe_pin: GPIO0<'static>) {
|
||||
let mut oe_lvl_shifter =
|
||||
Output::new(oe_pin, esp_hal::gpio::Level::Low, OutputConfig::default().with_drive_mode(esp_hal::gpio::DriveMode::PushPull).with_drive_strength(esp_hal::gpio::DriveStrength::_10mA));
|
||||
let mut oe_lvl_shifter = Output::new(
|
||||
oe_pin,
|
||||
esp_hal::gpio::Level::Low,
|
||||
OutputConfig::default()
|
||||
.with_drive_mode(esp_hal::gpio::DriveMode::PushPull)
|
||||
.with_drive_strength(esp_hal::gpio::DriveStrength::_10mA),
|
||||
);
|
||||
oe_lvl_shifter.set_high();
|
||||
}
|
||||
|
||||
@ -167,24 +170,14 @@ fn setup_spi(
|
||||
sck: GPIO19<'static>,
|
||||
miso: GPIO20<'static>,
|
||||
mosi: GPIO18<'static>,
|
||||
cs: GPIO2<'static>,
|
||||
) -> Spi<'static, Async> {
|
||||
) -> Spi<'static, Blocking> {
|
||||
let spi = match Spi::new(spi2, Spi_config::default()) {
|
||||
Ok(spi) => spi
|
||||
.with_sck(sck)
|
||||
.with_miso(miso)
|
||||
.with_mosi(mosi)
|
||||
.with_cs(cs)
|
||||
.into_async(),
|
||||
Ok(spi) => spi.with_sck(sck).with_miso(miso).with_mosi(mosi),
|
||||
Err(e) => panic!("Failed to initialize SPI: {:?}", e),
|
||||
};
|
||||
spi
|
||||
}
|
||||
|
||||
fn setup_sdcard(spi_device: Spi<'static, Async>) {
|
||||
//let sdcard = SdCard::new(spi_device as embedded_hal::spi::SpiDevice(), delayer)
|
||||
}
|
||||
|
||||
pub fn setup_buzzer(buzzer_gpio: GPIO21<'static>) -> Output<'static> {
|
||||
let config = esp_hal::gpio::OutputConfig::default()
|
||||
.with_drive_strength(esp_hal::gpio::DriveStrength::_40mA);
|
||||
|
84
src/init/sd_card.rs
Normal file
84
src/init/sd_card.rs
Normal file
@ -0,0 +1,84 @@
|
||||
use alloc::vec::Vec;
|
||||
use embassy_time::Delay;
|
||||
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};
|
||||
|
||||
pub struct DummyTimesource;
|
||||
|
||||
impl TimeSource for DummyTimesource {
|
||||
fn get_timestamp(&self) -> Timestamp {
|
||||
Timestamp {
|
||||
year_since_1970: 0,
|
||||
zero_indexed_month: 0,
|
||||
zero_indexed_day: 0,
|
||||
hours: 0,
|
||||
minutes: 0,
|
||||
seconds: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type VolMgr = VolumeManager<
|
||||
SdCard<ExclusiveDevice<Spi<'static, Blocking>, Output<'static>, Delay>, Delay>,
|
||||
DummyTimesource,
|
||||
>;
|
||||
|
||||
pub fn setup_sdcard(spi_bus: Spi<'static, Blocking>, cs_pin: Output<'static>) -> SDCardPersistence {
|
||||
let spi_device = ExclusiveDevice::new(spi_bus, cs_pin, Delay).unwrap();
|
||||
let sd_card = SdCard::new(spi_device, Delay);
|
||||
let vol_mgr = VolumeManager::new(sd_card, DummyTimesource);
|
||||
|
||||
SDCardPersistence { vol_mgr }
|
||||
}
|
||||
|
||||
pub struct SDCardPersistence {
|
||||
vol_mgr: VolMgr,
|
||||
}
|
||||
|
||||
impl Persistence for SDCardPersistence {
|
||||
async fn load_day(&mut self, day: crate::store::Date) -> Option<AttendanceDay> {
|
||||
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("days/TODO", embedded_sdmmc::Mode::ReadOnly)
|
||||
.unwrap();
|
||||
|
||||
let mut read_buffer: [u8; 1024] = [0; 1024];
|
||||
let read = file.read(&mut read_buffer).unwrap();
|
||||
file.close().unwrap();
|
||||
|
||||
let day: AttendanceDay = serde_json::from_slice(&read_buffer).unwrap();
|
||||
|
||||
Some(day)
|
||||
}
|
||||
|
||||
async fn save_day(&mut self, day: Date, data: &AttendanceDay) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn load_mapping(&mut self) -> Option<crate::store::IDMapping> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn save_mapping(&mut self, data: &crate::store::IDMapping) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn list_days(&mut self) -> Vec<Date> {
|
||||
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::new();
|
||||
days_dir
|
||||
.iterate_dir(|e| {
|
||||
days.push(1);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
days
|
||||
}
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
use crate::store::persistence::Persistence;
|
||||
|
||||
use super::Date;
|
||||
use super::IDMapping;
|
||||
use super::TallyID;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::vec::Vec;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct AttendanceDay {
|
||||
date: Date,
|
||||
ids: Vec<TallyID>,
|
||||
@ -30,42 +32,63 @@ impl AttendanceDay {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IDStore {
|
||||
pub days: BTreeMap<Date, AttendanceDay>,
|
||||
pub struct IDStore<T: Persistence> {
|
||||
pub current_day: AttendanceDay,
|
||||
pub mapping: IDMapping,
|
||||
persistence_layer: T,
|
||||
}
|
||||
|
||||
impl IDStore {
|
||||
pub fn new() -> Self {
|
||||
IDStore {
|
||||
days: BTreeMap::new(),
|
||||
mapping: IDMapping::new(),
|
||||
impl<T: Persistence> IDStore<T> {
|
||||
pub async fn new_from_storage(mut persistence_layer: T) -> Self {
|
||||
let mapping = match persistence_layer.load_mapping().await {
|
||||
Some(map) => map,
|
||||
None => IDMapping::new(),
|
||||
};
|
||||
|
||||
let current_date: Date = 1;
|
||||
|
||||
let day = persistence_layer
|
||||
.load_day(current_date)
|
||||
.await
|
||||
.unwrap_or(AttendanceDay::new(current_date));
|
||||
|
||||
Self {
|
||||
current_day: day,
|
||||
mapping,
|
||||
persistence_layer,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_storage() -> Self {
|
||||
// TODO: implement
|
||||
todo!()
|
||||
async fn persist_day(&mut self) {
|
||||
self.persistence_layer
|
||||
.save_day(self.current_day.date, &self.current_day)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn persist_mapping(&mut self) {
|
||||
self.persistence_layer.save_mapping(&self.mapping).await
|
||||
}
|
||||
|
||||
/// Add a new id for the current day
|
||||
/// Returns false if ID is already present at the current day.
|
||||
pub fn add_id(&mut self, id: TallyID) -> bool {
|
||||
self.get_current_day().add_id(id)
|
||||
}
|
||||
pub async fn add_id(&mut self, id: TallyID) -> bool {
|
||||
let current_date: Date = 1;
|
||||
|
||||
/// Get the `AttendanceDay` of the current day
|
||||
/// Creates a new if not exists
|
||||
pub fn get_current_day(&mut self) -> &mut AttendanceDay {
|
||||
let current_day: Date = 1;
|
||||
|
||||
if self.days.contains_key(¤t_day) {
|
||||
return self.days.get_mut(¤t_day).unwrap();
|
||||
if self.current_day.date == current_date {
|
||||
let changed = self.current_day.add_id(id);
|
||||
if changed {
|
||||
self.persist_day().await;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
self.days
|
||||
.insert(current_day, AttendanceDay::new(current_day));
|
||||
let new_day = AttendanceDay::new(current_date);
|
||||
self.current_day = new_day;
|
||||
|
||||
self.days.get_mut(¤t_day.clone()).unwrap()
|
||||
let changed = self.current_day.add_id(id);
|
||||
if changed {
|
||||
self.persist_day().await;
|
||||
}
|
||||
changed
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
mod id_mapping;
|
||||
pub mod persistence;
|
||||
mod id_store;
|
||||
|
||||
pub use id_mapping::{IDMapping, Name};
|
||||
pub use id_store::IDStore;
|
||||
pub use id_store::{IDStore,AttendanceDay};
|
||||
|
||||
pub type TallyID = [u8; 8];
|
||||
pub type Date = u64;
|
||||
|
12
src/store/persistence.rs
Normal file
12
src/store/persistence.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::store::{Date, IDMapping, id_store::AttendanceDay};
|
||||
|
||||
pub trait Persistence {
|
||||
async fn load_day(&mut self, day: Date) -> Option<AttendanceDay>;
|
||||
async fn save_day(&mut self, day: Date, data: &AttendanceDay);
|
||||
async fn list_days(&mut self) -> Vec<Date>;
|
||||
|
||||
async fn load_mapping(&mut self) -> Option<IDMapping>;
|
||||
async fn save_mapping(&mut self, data: &IDMapping);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user