Moved quasi-devices into the devices module and made event related device traits part of the event module
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-04-24 04:28:17 +02:00
parent 28ce9c9d82
commit 40c0ac5144
15 changed files with 64 additions and 66 deletions

96
src/devices/presence.rs Normal file
View File

@@ -0,0 +1,96 @@
use std::collections::HashMap;
use async_trait::async_trait;
use rumqttc::Publish;
use serde::Deserialize;
use tracing::{debug, warn};
use crate::{
config::MqttDeviceConfig,
devices::Device,
event::OnMqtt,
event::{self, Event, EventChannel},
messages::PresenceMessage,
};
#[derive(Debug, Deserialize)]
pub struct PresenceConfig {
#[serde(flatten)]
pub mqtt: MqttDeviceConfig,
}
pub const DEFAULT_PRESENCE: bool = false;
#[derive(Debug)]
pub struct Presence {
tx: event::Sender,
mqtt: MqttDeviceConfig,
devices: HashMap<String, bool>,
current_overall_presence: bool,
}
impl Presence {
pub fn new(config: PresenceConfig, event_channel: &EventChannel) -> Self {
Self {
tx: event_channel.get_tx(),
mqtt: config.mqtt,
devices: HashMap::new(),
current_overall_presence: DEFAULT_PRESENCE,
}
}
}
impl Device for Presence {
fn get_id(&self) -> &str {
"presence"
}
}
#[async_trait]
impl OnMqtt for Presence {
fn topics(&self) -> Vec<&str> {
vec![&self.mqtt.topic]
}
async fn on_mqtt(&mut self, message: Publish) {
let offset = self
.mqtt
.topic
.find('+')
.or(self.mqtt.topic.find('#'))
.expect("Presence::create fails if it does not contain wildcards");
let device_name = message.topic[offset..].to_owned();
if message.payload.is_empty() {
// Remove the device from the map
debug!("State of device [{device_name}] has been removed");
self.devices.remove(&device_name);
} else {
let present = match PresenceMessage::try_from(message) {
Ok(state) => state.presence(),
Err(err) => {
warn!("Failed to parse message: {err}");
return;
}
};
debug!("State of device [{device_name}] has changed: {}", present);
self.devices.insert(device_name, present);
}
let overall_presence = self.devices.iter().any(|(_, v)| *v);
if overall_presence != self.current_overall_presence {
debug!("Overall presence updated: {overall_presence}");
self.current_overall_presence = overall_presence;
if self
.tx
.send(Event::Presence(overall_presence))
.await
.is_err()
{
warn!("There are no receivers on the event channel");
}
}
}
}