Compare commits

...

4 Commits

Author SHA1 Message Date
0f5ca88ae4 fixed many warning by removing unused imports
Removed a lot of imports — believe me, so many imports were totally
unnecessary. Nobody’s seen imports like these. Cleaned up the code, made
it faster, smarter, the best code. People are talking about it!
Tremendous work by me. Some say i am the best at it. It may be true.
2025-10-08 01:54:51 +02:00
9dd2f88cbc implemented SSE 2025-10-08 01:44:32 +02:00
aa91d69f0b explicit type of tallyid channels 2025-10-08 01:43:48 +02:00
b13ae76bc5 moved TallyID str function to right module 2025-10-08 01:42:25 +02:00
13 changed files with 112 additions and 102 deletions

View File

@@ -2,7 +2,7 @@ use embassy_time::{Duration, Timer};
use esp_hal::{Async, uart::Uart};
use log::{debug, info};
use crate::{TallyPublisher, store::TallyID};
use crate::TallyPublisher;
#[embassy_executor::task]
pub async fn rfid_reader_task(mut uart_device: Uart<'static, Async>, chan: TallyPublisher) {

View File

@@ -1,3 +1,4 @@
use chrono::{TimeZone, Utc};
use ds3231::{
Config, DS3231, DS3231Error, InterruptControl, Oscillator, SquareWaveFrequency,
TimeRepresentation,
@@ -9,7 +10,6 @@ use esp_hal::{
use log::{debug, error, info};
use crate::{FEEDBACK_STATE, drivers, feedback, store::Date};
use chrono::{TimeZone, Utc};
include!(concat!(env!("OUT_DIR"), "/build_time.rs"));
@@ -70,7 +70,6 @@ impl RTCClock {
buffer
}
}
fn unix_to_ymd_string(timestamp: u64) -> (u16, u8, u8) {

View File

@@ -1,8 +1,7 @@
use embassy_time::{Delay, Duration, Timer};
use esp_hal::{delay, gpio::Output, peripherals, rmt::ConstChannelAccess};
use embassy_time::{Duration, Timer};
use esp_hal::{peripherals, rmt::ConstChannelAccess};
use esp_hal_smartled::SmartLedsAdapterAsync;
use init::hardware;
use log::{debug, error, info};
use log::debug;
use smart_leds::SmartLedsWriteAsync;
use smart_leds::colors::{BLACK, GREEN, RED, YELLOW};
use smart_leds::{brightness, colors::BLUE};

View File

@@ -1,13 +1,10 @@
use core::cell::RefCell;
use bleps::att::Att;
use critical_section::Mutex;
use ds3231::InterruptControl;
use embassy_executor::Spawner;
use embassy_net::Stack;
use embassy_time::{Duration, Timer};
use esp_hal::gpio::{Input, InputConfig};
use esp_hal::Blocking;
use esp_hal::gpio::Input;
use esp_hal::i2c::master::Config;
use esp_hal::peripherals::{
GPIO0, GPIO1, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23, I2C0, RMT, SPI2,
@@ -15,8 +12,6 @@ use esp_hal::peripherals::{
};
use esp_hal::rmt::{ConstChannelAccess, Rmt};
use esp_hal::spi::master::{Config as Spi_config, Spi};
use esp_hal::Blocking;
use esp_hal::time::Rate;
use esp_hal::timer::timg::TimerGroup;
use esp_hal::{
@@ -28,16 +23,12 @@ use esp_hal::{
uart::Uart,
};
use esp_hal_smartled::{SmartLedsAdapterAsync, buffer_size_async};
use esp_println::dbg;
use esp_println::logger::init_logger;
use log::{debug, error, info};
use log::{debug, error};
use crate::FEEDBACK_STATE;
use crate::init::network;
use crate::init::sd_card::{setup_sdcard, SDCardPersistence};
use crate::init::sd_card::{SDCardPersistence, setup_sdcard};
use crate::init::wifi;
use crate::store::AttendanceDay;
use crate::store::persistence::Persistence;
/*************************************************
* GPIO Pinout Xiao Esp32c6

View File

@@ -1,5 +1,4 @@
use core::{net::Ipv4Addr, str::FromStr};
use embassy_executor::Spawner;
use embassy_net::{Ipv4Cidr, Runner, Stack, StackResources, StaticConfigV4};
use embassy_time::{Duration, Timer};

View File

@@ -10,7 +10,7 @@ use embassy_sync::{
blocking_mutex::raw::{CriticalSectionRawMutex, NoopRawMutex},
mutex::Mutex,
pubsub::{
PubSubChannel, Publisher,
PubSubChannel, Publisher, Subscriber,
WaitResult::{Lagged, Message},
},
signal::Signal,
@@ -21,14 +21,14 @@ use esp_hal::{gpio::InputConfig, peripherals};
use log::{debug, info};
use static_cell::make_static;
extern crate alloc;
use crate::{
init::sd_card::SDCardPersistence,
store::{Date, IDStore, TallyID},
webserver::start_webserver,
};
extern crate alloc;
mod drivers;
mod feedback;
mod init;
@@ -39,6 +39,7 @@ static FEEDBACK_STATE: Signal<CriticalSectionRawMutex, feedback::FeedbackState>
type TallyChannel = PubSubChannel<NoopRawMutex, TallyID, 8, 2, 1>;
type TallyPublisher = Publisher<'static, NoopRawMutex, TallyID, 8, 2, 1>;
type TallySubscriber = Subscriber<'static, NoopRawMutex, TallyID, 8, 2, 1>;
type UsedStore = IDStore<SDCardPersistence>;
#[esp_hal_embassy::main]
@@ -54,12 +55,12 @@ async fn main(mut spawner: Spawner) {
let shared_store = Rc::new(Mutex::new(store));
let chan: &'static mut TallyChannel = make_static!(PubSubChannel::new());
let publisher = chan.publisher().unwrap();
let mut sub = chan.subscriber().unwrap();
let publisher: TallyPublisher = chan.publisher().unwrap();
let mut sub: TallySubscriber = chan.subscriber().unwrap();
wait_for_stack_up(stack).await;
start_webserver(&mut spawner, stack, shared_store.clone());
start_webserver(&mut spawner, stack, shared_store.clone(), chan);
/****************************** Spawning tasks ***********************************/
debug!("spawing NFC reader task...");

View File

@@ -1,8 +1,9 @@
use super::TallyID;
use alloc::collections::BTreeMap;
use alloc::string::String;
use serde::{Deserialize, Serialize};
use super::TallyID;
#[derive(Clone, Serialize, Deserialize)]
pub struct Name {
pub first: String,

View File

@@ -1,13 +1,11 @@
use crate::drivers::rtc;
use crate::drivers::rtc::RTCClock;
use crate::store::persistence::Persistence;
use alloc::vec::Vec;
use serde::Deserialize;
use serde::Serialize;
use super::Date;
use super::IDMapping;
use super::TallyID;
use alloc::vec::Vec;
use serde::Deserialize;
use serde::Serialize;
use crate::store::persistence::Persistence;
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct AttendanceDay {
@@ -75,7 +73,6 @@ impl<T: Persistence> IDStore<T> {
/// 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 {
if self.current_day.date == current_date {
let changed = self.current_day.add_id(id);
if changed {

View File

@@ -1,9 +1,48 @@
mod id_mapping;
pub mod persistence;
mod id_store;
use heapless::String;
pub use id_mapping::{IDMapping, Name};
pub use id_store::{IDStore,AttendanceDay};
mod id_mapping;
pub mod persistence;
mod id_store;
pub type TallyID = [u8; 6];
pub type Date = [u8; 10];
pub fn hex_string_to_tally_id(s: &str) -> Option<TallyID> {
let bytes = s.as_bytes();
if bytes.len() != 12 {
return None;
}
let mut out: TallyID = [0;6];
for i in 0..6 {
let hi = hex_val(bytes[2 * i])?;
let lo = hex_val(bytes[2 * i + 1])?;
out[i] = (hi << 4) | lo;
}
Some(out)
}
pub fn tally_id_to_hex_string(bytes: TallyID) -> Option<String<12>> {
const HEX_CHARS: &[u8; 16] = b"0123456789abcdef";
let mut s: String<12> = String::new();
for &b in &bytes {
s.push(HEX_CHARS[(b >> 4) as usize] as char).ok()?;
s.push(HEX_CHARS[(b & 0x0F) as usize] as char).ok()?;
}
Some(s)
}
fn hex_val(b: u8) -> Option<u8> {
match b {
b'0'..=b'9' => Some(b - b'0'),
b'a'..=b'f' => Some(b - b'a' + 10),
b'A'..=b'F' => Some(b - b'A' + 10),
_ => None,
}
}

View File

@@ -6,8 +6,8 @@ use picoserve::{
use serde::Deserialize;
use crate::{
store::{Name, TallyID},
webserver::app::AppState,
store::{Name, hex_string_to_tally_id},
webserver::{app::AppState, sse::IDEvents},
};
#[derive(Deserialize)]
@@ -16,30 +16,6 @@ pub struct NewMapping {
name: Name,
}
pub fn hex_string_to_tally_id(s: &str) -> Option<TallyID> {
let bytes = s.as_bytes();
if bytes.len() != 24 {
return None;
}
let mut out = [0u8; 12];
for i in 0..12 {
let hi = hex_val(bytes[2 * i])?;
let lo = hex_val(bytes[2 * i + 1])?;
out[i] = (hi << 4) | lo;
}
Some(out)
}
fn hex_val(b: u8) -> Option<u8> {
match b {
b'0'..=b'9' => Some(b - b'0'),
b'a'..=b'f' => Some(b - b'a' + 10),
b'A'..=b'F' => Some(b - b'A' + 10),
_ => None,
}
}
/*
* #[get("/api/idevent")]
* #[get("/api/csv")]
@@ -64,3 +40,7 @@ pub async fn add_mapping(
let tally_id = hex_string_to_tally_id(&data.id).unwrap();
store.mapping.add_mapping(tally_id, data.name);
}
pub async fn get_idevent(State(state): State<AppState>) -> impl IntoResponse {
response::EventStream(IDEvents(state.chan.subscriber().unwrap()))
}

View File

@@ -3,15 +3,17 @@ use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
use picoserve::{AppWithStateBuilder, routing::get};
use crate::{
TallyChannel, UsedStore,
webserver::{
api::{add_mapping, get_mapping},
api::{add_mapping, get_idevent, get_mapping},
assets::Assets,
}, UsedStore,
},
};
#[derive(Clone)]
pub struct AppState {
pub store: Rc<Mutex<CriticalSectionRawMutex, UsedStore>>,
pub chan: &'static TallyChannel,
}
pub struct AppProps;
@@ -23,9 +25,6 @@ impl AppWithStateBuilder for AppProps {
fn build_app(self) -> picoserve::Router<Self::PathRouter, AppState> {
picoserve::Router::from_service(Assets)
.route("/api/mapping", get(get_mapping).post(add_mapping))
// .route(
// "/api/idevent",
// get(move || response::EventStream(Events(self.chan))),
// )
.route("/api/idevent", get(get_idevent))
}
}

View File

@@ -7,14 +7,14 @@ use picoserve::{AppRouter, AppWithStateBuilder};
use static_cell::make_static;
use crate::{
UsedStore,
TallyChannel, UsedStore,
webserver::app::{AppProps, AppState},
};
mod assets;
// mod sse;
mod api;
mod app;
mod assets;
mod sse;
pub const WEB_TAKS_SIZE: usize = 3; // Up this number if request start fail with Timeouts.
@@ -22,10 +22,11 @@ pub fn start_webserver(
spawner: &mut Spawner,
stack: Stack<'static>,
store: Rc<Mutex<CriticalSectionRawMutex, UsedStore>>,
chan: &'static TallyChannel,
) {
let app = make_static!(AppProps.build_app());
let state = make_static!(AppState { store });
let state = make_static!(AppState { store, chan });
let config = make_static!(picoserve::Config::new(picoserve::Timeouts {
start_read_request: Some(Duration::from_secs(5)),

View File

@@ -2,9 +2,11 @@ use embassy_time::{Duration, Timer};
use log::warn;
use picoserve::response;
pub struct Events(pub TallySubscriber);
use crate::{TallySubscriber, store::tally_id_to_hex_string};
impl response::sse::EventSource for Events {
pub struct IDEvents(pub TallySubscriber);
impl response::sse::EventSource for IDEvents {
async fn write_events<W: picoserve::io::Write>(
mut self,
mut writer: response::sse::EventWriter<W>,
@@ -16,7 +18,9 @@ impl response::sse::EventSource for Events {
match sel.await {
embassy_futures::select::Either::First(msg) => match msg {
embassy_sync::pubsub::WaitResult::Message(id) => {
writer.write_event("msg", id.to_string().as_str()).await?
writer
.write_event("msg", tally_id_to_hex_string(id).unwrap().as_str())
.await?
}
embassy_sync::pubsub::WaitResult::Lagged(_) => {
warn!("SSE subscriber got lagged");