diff --git a/src/discord.rs b/src/discord.rs index 088fe37..f0dd0ed 100644 --- a/src/discord.rs +++ b/src/discord.rs @@ -6,6 +6,10 @@ use serenity::all::{prelude::*, Color, CreateEmbed, CreateMessage}; use serenity::model::id::ChannelId; use tracing::{info, error}; +const COLOR_OPEN: Color = Color::new(0x00FF00); // Green for open +const COLOR_CLOSED: Color = Color::new(0xFF0000); // Red for closed +const COLOR_STARTUP: Color = Color::new(0xFFA500); // Orange for startup + pub struct DiscordClient { client: Client, channel_id: ChannelId, @@ -47,11 +51,11 @@ impl DiscordClient { crate::gpio::CircuitEvent::Closed => "We'll see you again soon.", }) .color(match event { - crate::gpio::CircuitEvent::Open => Color::new(0x00FF00), // Red for open - crate::gpio::CircuitEvent::Closed => Color::new(0xFF0000), // Green for closed + crate::gpio::CircuitEvent::Open => COLOR_OPEN, + crate::gpio::CircuitEvent::Closed => COLOR_CLOSED, }).thumbnail(match event { - crate::gpio::CircuitEvent::Open => "https://www.noisebridge.net/images/7/7f/Open.png", // Image that says "Open" - crate::gpio::CircuitEvent::Closed => "https://www.noisebridge.net/images/c/c9/Closed.png", // Image that says "Closed" + crate::gpio::CircuitEvent::Open => "https://www.noisebridge.net/images/7/7f/Open.png", + crate::gpio::CircuitEvent::Closed => "https://www.noisebridge.net/images/c/c9/Closed.png", }); if let Err(why) = self.channel_id.send_message(&self.client.http, CreateMessage::default().add_embed(embed)).await { @@ -71,7 +75,7 @@ impl DiscordClient { let embed = CreateEmbed::new() .title("Noisebell is starting up!") .description("The Noisebell service is initializing and will begin monitoring the space status.") - .color(Color::new(0xFFA500)) // Orange for startup + .color(COLOR_STARTUP) .thumbnail("https://cats.com/wp-content/uploads/2024/07/Beautiful-red-cat-stretches-and-shows-tongue.jpg"); if let Err(why) = self.channel_id.send_message(&self.client.http, CreateMessage::default().add_embed(embed)).await { diff --git a/src/gpio.rs b/src/gpio.rs index fba36d4..6bdb95d 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -2,7 +2,7 @@ use std::time::Duration; use std::fmt; use serde::{Serialize, Deserialize}; -use anyhow::Result; +use anyhow::{Result, Context}; use rppal::gpio::{Gpio, InputPin, Level}; #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] @@ -27,8 +27,11 @@ pub struct GpioMonitor { impl GpioMonitor { pub fn new(pin_number: u8, poll_interval: Duration) -> Result { - let gpio = Gpio::new()?; - let pin = gpio.get(pin_number)?.into_input_pullup(); + let gpio = Gpio::new() + .context("Failed to initialize GPIO")?; + let pin = gpio.get(pin_number) + .context(format!("Failed to get GPIO pin {}", pin_number))? + .into_input_pullup(); Ok(Self { pin, poll_interval }) } @@ -38,6 +41,7 @@ impl GpioMonitor { F: FnMut(CircuitEvent) + Send + 'static, { let mut previous_state = self.get_current_state(); + callback(previous_state); // Send initial state loop { let current_state = self.get_current_state(); diff --git a/src/main.rs b/src/main.rs index 0e855ff..bcaf0ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,18 +11,25 @@ use tracing_appender::rolling::{RollingFileAppender, Rotation}; use tracing_subscriber::filter::LevelFilter; use tracing_subscriber::{fmt, layer::SubscriberExt, util::SubscriberInitExt}; +const DEFAULT_GPIO_PIN: u8 = 17; +const DEFAULT_POLL_INTERVAL_MS: u64 = 100; +const LOG_DIR: &str = "logs"; +const LOG_PREFIX: &str = "noisebell"; +const LOG_SUFFIX: &str = "log"; +const MAX_LOG_FILES: usize = 7; + #[tokio::main] async fn main() -> Result<()> { info!("creating logs directory"); - fs::create_dir_all("logs")?; + fs::create_dir_all(LOG_DIR)?; info!("initializing logging"); let file_appender = RollingFileAppender::builder() .rotation(Rotation::DAILY) - .filename_prefix("noisebell") - .filename_suffix("log") - .max_log_files(7) - .build("logs")?; + .filename_prefix(LOG_PREFIX) + .filename_suffix(LOG_SUFFIX) + .max_log_files(MAX_LOG_FILES) + .build(LOG_DIR)?; let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender); @@ -44,13 +51,11 @@ async fn main() -> Result<()> { discord_client.send_startup_message().await?; - const DEFAULT_GPIO_PIN: u8 = 17; - info!("initializing gpio monitor"); - let mut gpio_monitor = gpio::GpioMonitor::new(DEFAULT_GPIO_PIN, Duration::from_millis(100))?; - - // Send initial state - discord_client.clone().send_circuit_event(&gpio_monitor.get_current_state()).await?; + let mut gpio_monitor = gpio::GpioMonitor::new( + DEFAULT_GPIO_PIN, + Duration::from_millis(DEFAULT_POLL_INTERVAL_MS) + )?; // Set up the callback for state changes let callback = move |event: gpio::CircuitEvent| {