From 703bb1b48cd16dab3a97d83fccd2c7543c7fc4e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20B=C3=B6hm?= Date: Fri, 5 Jan 2024 16:52:45 +0100 Subject: [PATCH] Refactoring --- src/main.rs | 107 ++++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 54 deletions(-) diff --git a/src/main.rs b/src/main.rs index 31ae178..e0c9f4c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,76 +1,75 @@ -use std::env; -use std::thread::sleep; -use std::time::Duration; - use rppal::gpio::{Gpio, InputPin, Level}; -use spaceapi_dezentrale_client::Client; +use spaceapi_dezentrale_client::ClientBuilder; +use std::{env, time::Duration}; +use tokio::time::sleep; -// set your scripts for opening and closing the space here -static DOOR_PIN: u8 = 27; -// delays in seconds -static RECHECK_DELAY: u64 = 5; -static ANTI_BOUNCE_DELAY: u64 = 1; +// Static delays +static RECHECK_DELAY: Duration = Duration::from_secs(5); +static ANTI_BOUNCE_DELAY: Duration = Duration::from_secs(1); + +#[derive(Debug)] +enum DoorStatus { + Open, + Closed, +} #[tokio::main] async fn main() { env_logger::init(); + let door_pin = env::var("DOOR_PIN").unwrap_or("27".to_string()); + let door_pin = door_pin.parse().expect("A number for the DOOR_PIN"); + // setup log::debug!("Setup GPIO"); let gpio = Gpio::new().unwrap(); - let pin = gpio.get(DOOR_PIN).unwrap().into_input(); + let pin = gpio.get(door_pin).unwrap().into_input(); - let spaceapi_client = spaceapi_dezentrale_client::ClientBuilder::new() - .api_key(&env::var("API_KEY").unwrap()) - .base_url(&env::var("SPACEAPI_URL").unwrap()) + log::debug!("Build client"); + let spaceapi_client = ClientBuilder::new() + .api_key(&env::var("API_KEY").expect("Set API_KEY in environment")) + .base_url(&env::var("SPACEAPI_URL").expect("Set SPACEAPI_URL in environment")) .build() .unwrap(); - // get initial door status - let mut door_status_old = check_door(&pin); - let _ = push_door_status(&spaceapi_client, door_status_old).await; - loop { - // maybe not the best solution but the pi isn't doing anything else - log::debug!("Waiting {} secs to read the door status", RECHECK_DELAY); - sleep(Duration::from_secs(RECHECK_DELAY)); - - // read new status - let door_status_new = check_door(&pin); - log::debug!("Read {}", door_status_new); - - // if the new status isn't the old one - if door_status_old != door_status_new { - // wait for the switch to stop bouncing around - log::debug!("Waiting {} secs for recheck", ANTI_BOUNCE_DELAY); - sleep(Duration::from_secs(ANTI_BOUNCE_DELAY)); - // the new read status is still the same after a minute then push it to the api - if door_status_new == check_door(&pin) { - log::debug!("Check passed, applying new status"); - log::debug!("Pushing space status: Open = {}", door_status_new); - let _ = push_door_status(&spaceapi_client, door_status_new) - .await - .map_err(|err| format!("Problem while pushing door status: {err}")); - log::debug!("Saving space status: {}", door_status_new); - door_status_old = door_status_new; - } else { - log::debug!("Check wasn't successful") + log::debug!("Checking door status"); + let push_result = match check_door(&pin).await { + DoorStatus::Open => { + log::debug!("Door is open, sending keep open to server"); + spaceapi_client.keep_open().await.map(|_| ()) } + DoorStatus::Closed => { + log::debug!("Door is closed, sending explicit close to server"); + spaceapi_client.close().await + } + }; + let _ = push_result.map_err(|err| format!("Problem while pushing door status: {err}")); + + sleep(RECHECK_DELAY).await; + log::debug!("Waiting {RECHECK_DELAY:?} secs to read the door status"); + } +} + +async fn check_door(pin: &InputPin) -> DoorStatus { + // reading space status from door + let mut pin_state = pin.read(); + + // Anti bounce verification + loop { + sleep(ANTI_BOUNCE_DELAY).await; + let pin_state_check = pin.read(); + if pin_state_check == pin_state { + break; + } else { + pin_state = pin_state_check } } -} -fn check_door(pin: &InputPin) -> bool { - // reading space status from door - pin.read() == Level::Low -} - -async fn push_door_status(spaceapi: &Client, open: bool) -> Result<(), String> { - if open { - log::debug!("Sending keep open to server"); - spaceapi.keep_open().await.map(|_| ()) + log::debug!("Pin state is {pin_state}"); + if pin_state == Level::Low { + DoorStatus::Open } else { - log::debug!("Sending explicit close to server"); - spaceapi.close().await + DoorStatus::Closed } }