fabaccess-bffh/bffhd/actors/shelly.rs

68 lines
2.0 KiB
Rust
Raw Permalink Normal View History

2022-03-13 21:30:26 +01:00
use futures_util::future::BoxFuture;
2022-05-05 15:50:44 +02:00
use std::collections::HashMap;
2022-04-26 23:21:43 +02:00
2022-03-13 21:30:26 +01:00
use crate::actors::Actor;
2022-03-16 18:10:59 +01:00
use crate::db::ArchivedValue;
use crate::resources::modules::fabaccess::ArchivedStatus;
2022-03-13 21:30:26 +01:00
use crate::resources::state::State;
2022-05-05 15:50:44 +02:00
use rumqttc::{AsyncClient, QoS};
2022-03-13 21:30:26 +01:00
/// An actuator for a Shellie connected listening on one MQTT broker
///
/// This actuator will toggle the shellie with the given `name`.
/// If you need to toggle shellies on multiple brokers you need multiple instanced of this
/// actuator with different clients.
pub struct Shelly {
name: String,
client: AsyncClient,
topic: String,
}
impl Shelly {
pub fn new(name: String, client: AsyncClient, params: &HashMap<String, String>) -> Self {
let topic = if let Some(topic) = params.get("topic") {
format!("shellies/{}/relay/0/command", topic)
} else {
format!("shellies/{}/relay/0/command", name)
};
tracing::debug!(%name,%topic,"Starting shelly module");
2022-05-05 15:50:44 +02:00
Shelly {
name,
client,
topic,
}
2022-03-13 21:30:26 +01:00
}
/// Set the name to a new one. This changes the shelly that will be activated
pub fn set_name(&mut self, new_name: String) {
tracing::debug!(old=%self.name, new=%new_name, "Renaming shelly actor");
self.name = new_name;
}
}
impl Actor for Shelly {
2022-03-16 18:10:59 +01:00
fn apply(&mut self, state: ArchivedValue<State>) -> BoxFuture<'static, ()> {
2022-03-13 21:54:48 +01:00
tracing::debug!(?state, name=%self.name,
"Shelly changing state"
);
2022-03-16 18:10:59 +01:00
let pl = match state.as_ref().inner.state {
ArchivedStatus::InUse(_) => "on",
2022-03-13 21:30:26 +01:00
_ => "off",
};
let name = self.name.clone();
let client = self.client.clone();
let topic = self.topic.clone();
let f = async move {
let res = client.publish(topic, QoS::AtLeastOnce, false, pl).await;
if let Err(error) = res {
tracing::error!(?error, %name, "`Shelly` actor failed to update state");
}
};
return Box::pin(f);
}
}