You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
3.5 KiB

use crate::light::{Status, Update, Value, BRIGHTNESS, HUE, KELVIN, POWER, SATURATION};
use log::warn;
use rumqtt;
use rumqtt::{MqttClient, QoS};
pub struct MqttUpdates {
client: MqttClient,
updates: crossbeam_channel::Receiver<Status>,
}
impl MqttUpdates {
pub fn new(client: MqttClient, updates: crossbeam_channel::Receiver<Status>) -> Self {
MqttUpdates { client, updates }
}
pub fn add_light(&mut self, id: &str, lightname: &str) -> Result<(), rumqtt::ClientError> {
info!("Add light: {}", lightname);
self.client.publish(
format!("/{}/lights", crate::MQTT_ID),
QoS::AtLeastOnce,
false,
format!("{}:{}", id, lightname),
)?;
let base_url = format!("/{}/lights/{}/", crate::MQTT_ID, lightname);
self.client.publish(
base_url.clone() + "status/connected",
QoS::AtLeastOnce,
true,
"true",
)?;
self.client
.subscribe(base_url.clone() + "command/" + POWER, QoS::AtLeastOnce)?;
self.client
.subscribe(base_url.clone() + "command/" + BRIGHTNESS, QoS::AtLeastOnce)?;
self.client
.subscribe(base_url.clone() + "command/" + HUE, QoS::AtLeastOnce)?;
self.client
.subscribe(base_url.clone() + "command/" + SATURATION, QoS::AtLeastOnce)?;
self.client
.subscribe(base_url.clone() + "command/" + KELVIN, QoS::AtLeastOnce)?;
Ok(())
}
pub fn listen(&mut self) {
while let Ok(status) = self.updates.recv() {
match status {
Status::New(light) => {
if let Err(err) = self.add_light(&light.id, &light.label) {
warn!("{}", err);
continue;
}
self.handle_update(Update::new(&light.label, Value::Power(light.power)));
self.handle_update(Update::new(
&light.label,
Value::Brightness(light.brightness),
));
self.handle_update(Update::new(&light.label, Value::Hue(light.color.hue)));
self.handle_update(Update::new(
&light.label,
Value::Saturation(light.color.saturation),
));
self.handle_update(Update::new(
&light.label,
Value::Kelvin(light.color.kelvin),
));
}
Status::Remove(_name) => {
if let Err(err) = self.client.publish(
format!("/{}/lights/{}/status/connected", crate::MQTT_ID, _name),
QoS::AtLeastOnce,
true,
"false",
) {
warn!("{}", err);
}
}
Status::Update(update) => self.handle_update(update),
}
}
}
fn handle_update(&mut self, update: Update) {
let (detail, value) = update.status.unravel();
if let Err(err) = self.client.publish(
format!(
"/{}/lights/{}/status/{}",
crate::MQTT_ID,
update.lightname,
detail
),
QoS::AtLeastOnce,
true,
value.into_bytes(),
) {
warn!("{}", err);
}
}
}