automation_rs/src/light_sensor.rs

93 lines
2.2 KiB
Rust

use async_trait::async_trait;
use rumqttc::Publish;
use serde::Deserialize;
use tracing::{debug, trace, warn};
use crate::{
config::MqttDeviceConfig,
devices::Device,
event::{self, Event, EventChannel},
messages::BrightnessMessage,
traits::OnMqtt,
};
#[derive(Debug, Clone, Deserialize)]
pub struct LightSensorConfig {
#[serde(flatten)]
pub mqtt: MqttDeviceConfig,
pub min: isize,
pub max: isize,
}
pub const DEFAULT: bool = false;
#[derive(Debug)]
pub struct LightSensor {
tx: event::Sender,
mqtt: MqttDeviceConfig,
min: isize,
max: isize,
is_dark: bool,
}
impl LightSensor {
pub fn new(config: LightSensorConfig, event_channel: &EventChannel) -> Self {
Self {
tx: event_channel.get_tx(),
mqtt: config.mqtt,
min: config.min,
max: config.max,
is_dark: DEFAULT,
}
}
}
impl Device for LightSensor {
fn get_id(&self) -> &str {
"light_sensor"
}
}
#[async_trait]
impl OnMqtt for LightSensor {
fn topics(&self) -> Vec<&str> {
vec![&self.mqtt.topic]
}
async fn on_mqtt(&mut self, message: Publish) {
let illuminance = match BrightnessMessage::try_from(message) {
Ok(state) => state.illuminance(),
Err(err) => {
warn!("Failed to parse message: {err}");
return;
}
};
debug!("Illuminance: {illuminance}");
let is_dark = if illuminance <= self.min {
trace!("It is dark");
true
} else if illuminance >= self.max {
trace!("It is light");
false
} else {
trace!(
"In between min ({}) and max ({}) value, keeping current state: {}",
self.min,
self.max,
self.is_dark
);
self.is_dark
};
if is_dark != self.is_dark {
debug!("Dark state has changed: {is_dark}");
self.is_dark = is_dark;
if self.tx.send(Event::Darkness(is_dark)).await.is_err() {
warn!("There are no receivers on the event channel");
}
}
}
}