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, } impl MqttUpdates { pub fn new(client: MqttClient, updates: crossbeam_channel::Receiver) -> 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); } } }