Skip to main content

embedded_wg_display/util/
globals.rs

1//! Application-wide shared states for:
2//! - [`Storage`]
3//! - [`Display`]
4//! - [`EspTime`]
5//! - [`WidgetStore`]
6//!
7//! All `init_*` functions **must be called exactly once** during startup in `main()`, a seccond call to any init function will cause a panic.
8use crate::display::Display;
9use crate::runtime::widget::widget::clocks::Datetime;
10use crate::storage::Storage;
11use crate::util::esptime::EspTime;
12use crate::widget::store::WidgetStore;
13use alloc::vec::Vec;
14use common::models::WidgetStoreItem;
15use core::cell::RefCell;
16use critical_section::Mutex as CsMutex;
17use defmt::info;
18use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
19use embassy_sync::mutex::Mutex;
20
21type GlobalMutex<T> = Mutex<CriticalSectionRawMutex, Option<T>>;
22
23static STORAGE: GlobalMutex<Storage<'static>> = Mutex::new(None);
24static DISPLAY: GlobalMutex<Display> = Mutex::new(None);
25static ESP_TIME: CsMutex<RefCell<Option<EspTime>>> = CsMutex::new(RefCell::new(None));
26static WIDGET_STORE: GlobalMutex<WidgetStore> = Mutex::new(None);
27
28pub async fn init_storage(storage: Storage<'static>) {
29    let mut guard = STORAGE.lock().await;
30    if guard.is_some() {
31        panic!("Storage already initialized!");
32    }
33    *guard = Some(storage);
34    info!("Global storage initialized");
35}
36
37pub async fn with_storage<F, R>(f: F) -> R
38where
39    F: FnOnce(&mut Storage<'static>) -> R,
40{
41    let mut guard = STORAGE.lock().await;
42    let storage = guard
43        .as_mut()
44        .expect("Storage not initialized! Call init_storage() first");
45    f(storage)
46}
47
48pub async fn init_display(display: Display) {
49    let mut guard = DISPLAY.lock().await;
50    if guard.is_some() {
51        panic!("Display already initialized!");
52    }
53    *guard = Some(display);
54    info!("Global display initialized");
55}
56
57pub async fn with_display<F, R>(f: F) -> R
58where
59    F: FnOnce(&mut Display) -> R,
60{
61    let mut guard = DISPLAY.lock().await;
62    let display = guard
63        .as_mut()
64        .expect("Display not initialized! Call init_display() first");
65    f(display)
66}
67
68pub async fn console_println(text: &str) {
69    with_display(|display| display.console_println(text)).await;
70}
71
72pub fn init_time(time: EspTime) {
73    critical_section::with(|cs| {
74        let mut guard = ESP_TIME.borrow_ref_mut(cs);
75        if guard.is_some() {
76            panic!("Time already initialized! Call init_time() only once");
77        }
78        *guard = Some(time);
79    });
80    info!("Global time initialized");
81}
82
83pub fn with_time<F, R>(f: F) -> R
84where
85    F: FnOnce(&EspTime) -> R,
86{
87    critical_section::with(|cs| {
88        let guard = ESP_TIME.borrow_ref(cs);
89        let time = guard
90            .as_ref()
91            .expect("Time not initialized! Call init_time() first");
92        f(time)
93    })
94}
95
96pub fn now() -> Option<Datetime> {
97    with_time(EspTime::now)
98}
99
100pub async fn init_store(store: WidgetStore) {
101    let mut guard = WIDGET_STORE.lock().await;
102    if guard.is_some() {
103        panic!("WidgetStore already initialized! Call init_store() only once");
104    }
105    *guard = Some(store);
106    info!("Global widget store initialized");
107}
108
109pub async fn with_store<F, R>(f: F) -> R
110where
111    F: FnOnce(&WidgetStore) -> R,
112{
113    let guard = WIDGET_STORE.lock().await;
114    let store = guard
115        .as_ref()
116        .expect("WidgetStore not initialized! Call init_store() first");
117    f(store)
118}
119
120pub async fn get_store_items() -> Vec<WidgetStoreItem> {
121    with_store(|store| store.get_items().clone()).await
122}