use std::{ sync::{Arc, Mutex}, thread, }; use chrono::Local; use cron_tab::Cron; use gpio_cdev::{Chip, LineRequestFlags}; use ringer::Ringer; use crate::{ringer::BeepRinger, scheduler::Scheduler}; mod handler; mod router; mod scheduler; mod ringer; #[derive(Clone)] struct AppState { chip: Arc>, cron: Arc>>, scheduler: Arc> } fn app_state() -> AppState { let chip = Arc::new(Mutex::new(Chip::new("/dev/gpiochip0").unwrap())); let cron = Arc::new(Mutex::new(Cron::new(chrono::Local))); AppState { chip: chip.clone(), cron: cron.clone(), scheduler: Arc::new(Scheduler::new( BeepRinger::new(chip.clone()), cron.clone() )) } } #[tokio::main] async fn main() -> Result<(), Box> { let chip = Arc::new(Mutex::new(Chip::new("/dev/gpiochip0")?)); let mut cron = Cron::new(chrono::Local); let static_time = "0 30 7 * * *"; let app_state = app_state(); println!("Adding alarm {}", static_time); let job_result = cron.add_fn(static_time, move || { let mut guard = chip.lock().unwrap(); alarm(&mut *guard).unwrap(); }); let _ = job_result.expect("Failed to add job"); cron.start(); start_server(app_state).await; Ok(()) } async fn start_server(app_state: AppState) { let router = router::router(app_state); let listener = tokio::net::TcpListener::bind("0.0.0.0:8080").await.unwrap(); println!("Listening on http://0.0.0.0:8080"); axum::serve(listener, router).await.unwrap(); } fn alarm(chip: &mut Chip) -> Result<(), Box> { let beeper = chip .get_line(17)? .request(LineRequestFlags::OUTPUT, 0, "my-gpio")?; for _ in 0..5 { beeper.set_value(1)?; thread::sleep(std::time::Duration::from_secs(1)); beeper.set_value(0)?; thread::sleep(std::time::Duration::from_secs(1)); } Ok(()) }