From 28ce9c9d82db8390dc6dc08d2e2a8d56596f20ba Mon Sep 17 00:00:00 2001 From: Dreaded_X Date: Mon, 24 Apr 2023 02:50:30 +0200 Subject: [PATCH] Moved mqtt messages to a seperate file --- src/debug_bridge.rs | 2 +- src/devices/audio_setup.rs | 2 +- src/devices/contact_sensor.rs | 2 +- src/devices/ikea_outlet.rs | 2 +- src/devices/wake_on_lan.rs | 2 +- src/lib.rs | 1 + src/light_sensor.rs | 2 +- src/messages.rs | 196 ++++++++++++++++++++++++++++++++++ src/mqtt.rs | 192 +-------------------------------- src/presence.rs | 4 +- 10 files changed, 207 insertions(+), 198 deletions(-) create mode 100644 src/messages.rs diff --git a/src/debug_bridge.rs b/src/debug_bridge.rs index ec0db73..eae1063 100644 --- a/src/debug_bridge.rs +++ b/src/debug_bridge.rs @@ -6,7 +6,7 @@ use tracing::warn; use crate::{ config::MqttDeviceConfig, devices::Device, - mqtt::{DarknessMessage, PresenceMessage}, + messages::{DarknessMessage, PresenceMessage}, traits::OnDarkness, traits::OnPresence, }; diff --git a/src/devices/audio_setup.rs b/src/devices/audio_setup.rs index 1c92e95..87568c2 100644 --- a/src/devices/audio_setup.rs +++ b/src/devices/audio_setup.rs @@ -8,7 +8,7 @@ use crate::{ config::{self, CreateDevice, MqttDeviceConfig}, error::CreateDeviceError, event::EventChannel, - mqtt::{RemoteAction, RemoteMessage}, + messages::{RemoteAction, RemoteMessage}, traits::OnMqtt, traits::OnPresence, }; diff --git a/src/devices/contact_sensor.rs b/src/devices/contact_sensor.rs index 15dc791..7fe0b8b 100644 --- a/src/devices/contact_sensor.rs +++ b/src/devices/contact_sensor.rs @@ -10,7 +10,7 @@ use crate::{ config::{CreateDevice, MqttDeviceConfig}, error::{CreateDeviceError, MissingWildcard}, event::EventChannel, - mqtt::{ContactMessage, PresenceMessage}, + messages::{ContactMessage, PresenceMessage}, presence, traits::OnMqtt, traits::OnPresence, diff --git a/src/devices/ikea_outlet.rs b/src/devices/ikea_outlet.rs index 6cd715c..e3a0e79 100644 --- a/src/devices/ikea_outlet.rs +++ b/src/devices/ikea_outlet.rs @@ -17,7 +17,7 @@ use crate::config::{CreateDevice, InfoConfig, MqttDeviceConfig}; use crate::devices::Device; use crate::error::CreateDeviceError; use crate::event::EventChannel; -use crate::mqtt::OnOffMessage; +use crate::messages::OnOffMessage; use crate::traits::OnMqtt; use crate::traits::OnPresence; diff --git a/src/devices/wake_on_lan.rs b/src/devices/wake_on_lan.rs index 15adbf6..fb78395 100644 --- a/src/devices/wake_on_lan.rs +++ b/src/devices/wake_on_lan.rs @@ -17,7 +17,7 @@ use crate::{ config::{CreateDevice, InfoConfig, MqttDeviceConfig}, error::CreateDeviceError, event::EventChannel, - mqtt::ActivateMessage, + messages::ActivateMessage, traits::OnMqtt, }; diff --git a/src/lib.rs b/src/lib.rs index 8efedfb..de9558f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ pub mod error; pub mod event; pub mod hue_bridge; pub mod light_sensor; +pub mod messages; pub mod mqtt; pub mod ntfy; pub mod presence; diff --git a/src/light_sensor.rs b/src/light_sensor.rs index a0c7cfb..82328d2 100644 --- a/src/light_sensor.rs +++ b/src/light_sensor.rs @@ -7,7 +7,7 @@ use crate::{ config::MqttDeviceConfig, devices::Device, event::{self, Event, EventChannel}, - mqtt::BrightnessMessage, + messages::BrightnessMessage, traits::OnMqtt, }; diff --git a/src/messages.rs b/src/messages.rs new file mode 100644 index 0000000..cc220dd --- /dev/null +++ b/src/messages.rs @@ -0,0 +1,196 @@ +use std::time::{SystemTime, UNIX_EPOCH}; + +use rumqttc::Publish; +use serde::{Deserialize, Serialize}; + +use crate::error::ParseError; + +// Message used to turn on and off devices and receiving their state +#[derive(Debug, Serialize, Deserialize)] +pub struct OnOffMessage { + state: String, +} + +impl OnOffMessage { + pub fn new(state: bool) -> Self { + Self { + state: if state { "ON" } else { "OFF" }.into(), + } + } + + pub fn state(&self) -> bool { + self.state == "ON" + } +} + +impl TryFrom for OnOffMessage { + type Error = ParseError; + + fn try_from(message: Publish) -> Result { + serde_json::from_slice(&message.payload) + .or(Err(ParseError::InvalidPayload(message.payload.clone()))) + } +} + +// Message send to request activating a device +#[derive(Debug, Deserialize)] +pub struct ActivateMessage { + activate: bool, +} + +impl ActivateMessage { + pub fn activate(&self) -> bool { + self.activate + } +} + +impl TryFrom for ActivateMessage { + type Error = ParseError; + + fn try_from(message: Publish) -> Result { + serde_json::from_slice(&message.payload) + .or(Err(ParseError::InvalidPayload(message.payload.clone()))) + } +} + +// Actions that can be performed by a remote +#[derive(Debug, Deserialize, Copy, Clone)] +#[serde(rename_all = "snake_case")] +pub enum RemoteAction { + On, + Off, + BrightnessMoveUp, + BrightnessMoveDown, + BrightnessStop, +} + +// Message used to report the action performed by a remote +#[derive(Debug, Deserialize)] +pub struct RemoteMessage { + action: RemoteAction, +} + +impl RemoteMessage { + pub fn action(&self) -> RemoteAction { + self.action + } +} + +impl TryFrom for RemoteMessage { + type Error = ParseError; + + fn try_from(message: Publish) -> Result { + serde_json::from_slice(&message.payload) + .or(Err(ParseError::InvalidPayload(message.payload.clone()))) + } +} + +// Message used to report the current presence state +#[derive(Debug, Deserialize, Serialize)] +pub struct PresenceMessage { + state: bool, + updated: Option, +} + +impl PresenceMessage { + pub fn new(state: bool) -> Self { + Self { + state, + updated: Some( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time is after UNIX EPOCH") + .as_millis(), + ), + } + } + + pub fn presence(&self) -> bool { + self.state + } +} + +impl TryFrom for PresenceMessage { + type Error = ParseError; + + fn try_from(message: Publish) -> Result { + serde_json::from_slice(&message.payload) + .or(Err(ParseError::InvalidPayload(message.payload.clone()))) + } +} + +// Message use to report the state of a light sensor +#[derive(Debug, Deserialize)] +pub struct BrightnessMessage { + illuminance: isize, +} + +impl BrightnessMessage { + pub fn illuminance(&self) -> isize { + self.illuminance + } +} + +impl TryFrom for BrightnessMessage { + type Error = ParseError; + + fn try_from(message: Publish) -> Result { + serde_json::from_slice(&message.payload) + .or(Err(ParseError::InvalidPayload(message.payload.clone()))) + } +} + +// Message to report the state of a contact sensor +#[derive(Debug, Deserialize)] +pub struct ContactMessage { + contact: bool, +} + +impl ContactMessage { + pub fn is_closed(&self) -> bool { + self.contact + } +} + +impl TryFrom for ContactMessage { + type Error = ParseError; + + fn try_from(message: Publish) -> Result { + serde_json::from_slice(&message.payload) + .or(Err(ParseError::InvalidPayload(message.payload.clone()))) + } +} + +// Message used to report the current darkness state +#[derive(Debug, Deserialize, Serialize)] +pub struct DarknessMessage { + state: bool, + updated: Option, +} + +impl DarknessMessage { + pub fn new(state: bool) -> Self { + Self { + state, + updated: Some( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("Time is after UNIX EPOCH") + .as_millis(), + ), + } + } + + pub fn is_dark(&self) -> bool { + self.state + } +} + +impl TryFrom for DarknessMessage { + type Error = ParseError; + + fn try_from(message: Publish) -> Result { + serde_json::from_slice(&message.payload) + .or(Err(ParseError::InvalidPayload(message.payload.clone()))) + } +} diff --git a/src/mqtt.rs b/src/mqtt.rs index 23846c9..560b0b9 100644 --- a/src/mqtt.rs +++ b/src/mqtt.rs @@ -1,14 +1,8 @@ -use std::time::{SystemTime, UNIX_EPOCH}; - -use serde::{Deserialize, Serialize}; use tracing::{debug, warn}; -use rumqttc::{Event, EventLoop, Incoming, Publish}; +use rumqttc::{Event, EventLoop, Incoming}; -use crate::{ - error::ParseError, - event::{self, EventChannel}, -}; +use crate::event::{self, EventChannel}; pub fn start(mut eventloop: EventLoop, event_channel: &EventChannel) { let tx = event_channel.get_tx(); @@ -31,185 +25,3 @@ pub fn start(mut eventloop: EventLoop, event_channel: &EventChannel) { } }); } - -#[derive(Debug, Serialize, Deserialize)] -pub struct OnOffMessage { - state: String, -} - -impl OnOffMessage { - pub fn new(state: bool) -> Self { - Self { - state: if state { "ON" } else { "OFF" }.into(), - } - } - - pub fn state(&self) -> bool { - self.state == "ON" - } -} - -impl TryFrom for OnOffMessage { - type Error = ParseError; - - fn try_from(message: Publish) -> Result { - serde_json::from_slice(&message.payload) - .or(Err(ParseError::InvalidPayload(message.payload.clone()))) - } -} - -#[derive(Debug, Deserialize)] -pub struct ActivateMessage { - activate: bool, -} - -impl ActivateMessage { - pub fn activate(&self) -> bool { - self.activate - } -} - -impl TryFrom for ActivateMessage { - type Error = ParseError; - - fn try_from(message: Publish) -> Result { - serde_json::from_slice(&message.payload) - .or(Err(ParseError::InvalidPayload(message.payload.clone()))) - } -} - -#[derive(Debug, Deserialize, Copy, Clone)] -#[serde(rename_all = "snake_case")] -pub enum RemoteAction { - On, - Off, - BrightnessMoveUp, - BrightnessMoveDown, - BrightnessStop, -} - -#[derive(Debug, Deserialize)] -pub struct RemoteMessage { - action: RemoteAction, -} - -impl RemoteMessage { - pub fn action(&self) -> RemoteAction { - self.action - } -} - -impl TryFrom for RemoteMessage { - type Error = ParseError; - - fn try_from(message: Publish) -> Result { - serde_json::from_slice(&message.payload) - .or(Err(ParseError::InvalidPayload(message.payload.clone()))) - } -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct PresenceMessage { - state: bool, - updated: Option, -} - -impl PresenceMessage { - pub fn new(state: bool) -> Self { - Self { - state, - updated: Some( - SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time is after UNIX EPOCH") - .as_millis(), - ), - } - } - - pub fn present(&self) -> bool { - self.state - } -} - -impl TryFrom for PresenceMessage { - type Error = ParseError; - - fn try_from(message: Publish) -> Result { - serde_json::from_slice(&message.payload) - .or(Err(ParseError::InvalidPayload(message.payload.clone()))) - } -} - -#[derive(Debug, Deserialize)] -pub struct BrightnessMessage { - illuminance: isize, -} - -impl BrightnessMessage { - pub fn illuminance(&self) -> isize { - self.illuminance - } -} - -impl TryFrom for BrightnessMessage { - type Error = ParseError; - - fn try_from(message: Publish) -> Result { - serde_json::from_slice(&message.payload) - .or(Err(ParseError::InvalidPayload(message.payload.clone()))) - } -} - -#[derive(Debug, Deserialize)] -pub struct ContactMessage { - contact: bool, -} - -impl ContactMessage { - pub fn is_closed(&self) -> bool { - self.contact - } -} - -impl TryFrom for ContactMessage { - type Error = ParseError; - - fn try_from(message: Publish) -> Result { - serde_json::from_slice(&message.payload) - .or(Err(ParseError::InvalidPayload(message.payload.clone()))) - } -} - -#[derive(Debug, Deserialize, Serialize)] -pub struct DarknessMessage { - state: bool, - updated: Option, -} - -impl DarknessMessage { - pub fn new(state: bool) -> Self { - Self { - state, - updated: Some( - SystemTime::now() - .duration_since(UNIX_EPOCH) - .expect("Time is after UNIX EPOCH") - .as_millis(), - ), - } - } - - pub fn present(&self) -> bool { - self.state - } -} - -impl TryFrom for DarknessMessage { - type Error = ParseError; - - fn try_from(message: Publish) -> Result { - serde_json::from_slice(&message.payload) - .or(Err(ParseError::InvalidPayload(message.payload.clone()))) - } -} diff --git a/src/presence.rs b/src/presence.rs index 6e98341..cdbdd16 100644 --- a/src/presence.rs +++ b/src/presence.rs @@ -9,7 +9,7 @@ use crate::{ config::MqttDeviceConfig, devices::Device, event::{self, Event, EventChannel}, - mqtt::PresenceMessage, + messages::PresenceMessage, traits::OnMqtt, }; @@ -67,7 +67,7 @@ impl OnMqtt for Presence { self.devices.remove(&device_name); } else { let present = match PresenceMessage::try_from(message) { - Ok(state) => state.present(), + Ok(state) => state.presence(), Err(err) => { warn!("Failed to parse message: {err}"); return;