Improved error handling

This commit is contained in:
2023-01-12 02:01:14 +01:00
parent e9d1cf554d
commit 13f5c87c03
18 changed files with 445 additions and 172 deletions

View File

@@ -4,10 +4,11 @@ use rumqttc::{AsyncClient, matches};
use tracing::{error, warn, debug};
use crate::config::MqttDeviceConfig;
use crate::error;
use crate::mqtt::{OnMqtt, RemoteMessage, RemoteAction};
use crate::presence::OnPresence;
use super::Device;
use super::{Device, DeviceBox, AsOnOff};
// @TODO Ideally we store am Arc to the childern devices,
// that way they hook into everything just like all other devices
@@ -20,10 +21,20 @@ pub struct AudioSetup {
}
impl AudioSetup {
pub async fn new(identifier: String, mqtt: MqttDeviceConfig, mixer: Box<dyn traits::OnOff + Sync + Send>, speakers: Box<dyn traits::OnOff + Sync + Send>, client: AsyncClient) -> Self {
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await.unwrap();
pub async fn build(identifier: &str, mqtt: MqttDeviceConfig, mixer: DeviceBox, speakers: DeviceBox, client: AsyncClient) -> error::Result<Self> {
// We expect the children devices to implement the OnOff trait
let mixer = match AsOnOff::consume(mixer) {
Some(mixer) => mixer,
None => Err(error::ExpectedOnOff::new(&(identifier.to_owned() + ".mixer")))?,
};
let speakers = match AsOnOff::consume(speakers) {
Some(speakers) => speakers,
None => Err(error::ExpectedOnOff::new(&(identifier.to_owned() + ".speakers")))?,
};
Self { identifier, mqtt, mixer, speakers }
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await?;
Ok(Self { identifier: identifier.to_owned(), mqtt, mixer, speakers })
}
}

View File

@@ -5,7 +5,7 @@ use rumqttc::{AsyncClient, matches};
use tokio::task::JoinHandle;
use tracing::{error, debug, warn};
use crate::{config::{MqttDeviceConfig, PresenceDeviceConfig}, mqtt::{OnMqtt, ContactMessage, PresenceMessage}, presence::OnPresence};
use crate::{config::{MqttDeviceConfig, PresenceDeviceConfig}, mqtt::{OnMqtt, ContactMessage, PresenceMessage}, presence::OnPresence, error};
use super::Device;
@@ -22,18 +22,18 @@ pub struct ContactSensor {
}
impl ContactSensor {
pub async fn new(identifier: String, mqtt: MqttDeviceConfig, presence: Option<PresenceDeviceConfig>, client: AsyncClient) -> Self {
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await.unwrap();
pub async fn build(identifier: &str, mqtt: MqttDeviceConfig, presence: Option<PresenceDeviceConfig>, client: AsyncClient) -> error::Result<Self> {
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await?;
Self {
identifier,
Ok(Self {
identifier: identifier.to_owned(),
mqtt,
presence,
client,
overall_presence: false,
is_closed: true,
handle: None,
}
})
}
}
@@ -97,7 +97,7 @@ impl OnMqtt for ContactSensor {
// This is to prevent the house from being marked as present for however long the
// timeout is set when leaving the house
if !self.overall_presence {
self.client.publish(topic, rumqttc::QoS::AtLeastOnce, false, serde_json::to_string(&PresenceMessage::new(true)).unwrap()).await.unwrap();
self.client.publish(topic.clone(), rumqttc::QoS::AtLeastOnce, false, serde_json::to_string(&PresenceMessage::new(true)).unwrap()).await.map_err(|err| warn!("Failed to publish presence on {topic}: {err}")).ok();
}
} else {
// Once the door is closed again we start a timeout for removing the presence
@@ -109,7 +109,7 @@ impl OnMqtt for ContactSensor {
debug!(id, "Starting timeout ({timeout:?}) for contact sensor...");
tokio::time::sleep(timeout).await;
debug!(id, "Removing door device!");
client.publish(topic, rumqttc::QoS::AtLeastOnce, false, "").await.unwrap();
client.publish(topic.clone(), rumqttc::QoS::AtLeastOnce, false, "").await.map_err(|err| warn!("Failed to publish presence on {topic}: {err}")).ok();
})
);
}

View File

@@ -4,12 +4,13 @@ use async_trait::async_trait;
use google_home::errors::ErrorCode;
use google_home::{GoogleHomeDevice, device, types::Type, traits::{self, OnOff}};
use rumqttc::{AsyncClient, Publish, matches};
use tracing::{debug, trace, error};
use tracing::{debug, trace, error, warn};
use tokio::task::JoinHandle;
use pollster::FutureExt as _;
use crate::config::{KettleConfig, InfoConfig, MqttDeviceConfig};
use crate::devices::Device;
use crate::error;
use crate::mqtt::{OnMqtt, OnOffMessage};
use crate::presence::OnPresence;
@@ -26,11 +27,11 @@ pub struct IkeaOutlet {
}
impl IkeaOutlet {
pub async fn new(identifier: String, info: InfoConfig, mqtt: MqttDeviceConfig, kettle: Option<KettleConfig>, client: AsyncClient) -> Self {
pub async fn build(identifier: &str, info: InfoConfig, mqtt: MqttDeviceConfig, kettle: Option<KettleConfig>, client: AsyncClient) -> error::Result<Self> {
// @TODO Handle potential errors here
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await.unwrap();
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await?;
Self{ identifier, info, mqtt, kettle, client, last_known_state: false, handle: None }
Ok(Self{ identifier: identifier.to_owned(), info, mqtt, kettle, client, last_known_state: false, handle: None })
}
}
@@ -38,7 +39,7 @@ async fn set_on(client: AsyncClient, topic: String, on: bool) {
let message = OnOffMessage::new(on);
// @TODO Handle potential errors here
client.publish(topic + "/set", rumqttc::QoS::AtLeastOnce, false, serde_json::to_string(&message).unwrap()).await.unwrap();
client.publish(topic.clone() + "/set", rumqttc::QoS::AtLeastOnce, false, serde_json::to_string(&message).unwrap()).await.map_err(|err| warn!("Failed to update state on {topic}: {err}")).ok();
}
impl Device for IkeaOutlet {

View File

@@ -13,9 +13,8 @@ pub struct KasaOutlet {
}
impl KasaOutlet {
pub fn new(identifier: String, ip: Ipv4Addr) -> Self {
// @TODO Get the current state of the outlet
Self { identifier, addr: (ip, 9999).into() }
pub fn new(identifier: &str, ip: Ipv4Addr) -> Self {
Self { identifier: identifier.to_owned(), addr: (ip, 9999).into() }
}
}

View File

@@ -3,8 +3,9 @@ use google_home::{GoogleHomeDevice, types::Type, device, traits::{self, Scene},
use tracing::{debug, error};
use rumqttc::{AsyncClient, Publish, matches};
use pollster::FutureExt as _;
use eui48::MacAddress;
use crate::{config::{InfoConfig, MqttDeviceConfig}, mqtt::{OnMqtt, ActivateMessage}};
use crate::{config::{InfoConfig, MqttDeviceConfig}, mqtt::{OnMqtt, ActivateMessage}, error};
use super::Device;
@@ -13,15 +14,15 @@ pub struct WakeOnLAN {
identifier: String,
info: InfoConfig,
mqtt: MqttDeviceConfig,
mac_address: String,
mac_address: MacAddress,
}
impl WakeOnLAN {
pub async fn new(identifier: String, info: InfoConfig, mqtt: MqttDeviceConfig, mac_address: String, client: AsyncClient) -> Self {
pub async fn build(identifier: &str, info: InfoConfig, mqtt: MqttDeviceConfig, mac_address: MacAddress, client: AsyncClient) -> error::Result<Self> {
// @TODO Handle potential errors here
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await.unwrap();
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await?;
Self { identifier, info, mqtt, mac_address }
Ok(Self { identifier: identifier.to_owned(), info, mqtt, mac_address })
}
}