use std::{ fmt::Debug, sync::{Arc, Mutex}, thread, }; use gpio_cdev::{Chip, LineRequestFlags}; pub trait Ringer: Send + Sync + Debug { fn ring(&self) -> Result<(), String>; } #[derive(Debug)] pub struct BeepRinger { chip: Arc>, } impl BeepRinger { fn beep(times: u32, chip: &mut Chip) -> Result<(), String> { let beeper = chip.get_line(17); let beeper = match beeper { Ok(beeper) => beeper, Err(e) => { println!("Error opening line: {}", e); return Err("Could not open Line to Beeper".to_string()); } }; let beeper = beeper.request(LineRequestFlags::OUTPUT, 0, "my-gpio"); let beeper = match beeper { Ok(beeper) => beeper, Err(e) => { println!("Error requesting line: {}", e); return Err("Could not request Line to Beeper".to_string()); } }; for _ in 0..times { beeper.set_value(1).map_err(|e| e.to_string())?; thread::sleep(std::time::Duration::from_secs(1)); beeper.set_value(0).map_err(|e| e.to_string())?; thread::sleep(std::time::Duration::from_secs(1)); } return Ok(()); } pub fn new(chip: Arc>) -> Self { Self { chip } } } impl Ringer for BeepRinger { fn ring(&self) -> Result<(), String> { let chip = self.chip.lock(); let mut chip = match chip { Ok(chip) => chip, Err(e) => { println!("Error opening chip: {}", e); return Err("Could not access Chip".to_string()); } }; BeepRinger::beep(5, &mut *chip)?; Ok(()) } } /// Used for local testing without an actual beeper or similar. The only thing it does is print /// that it's ringing. #[derive(Debug)] pub struct SilentRinger; impl SilentRinger { pub fn new() -> Self { Self {} } } impl Ringer for SilentRinger { fn ring(&self) -> Result<(), String> { println!("Ringing"); Ok(()) } }