Improved error handling
This commit is contained in:
@@ -4,7 +4,7 @@ use rumqttc::{AsyncClient, matches};
|
||||
use tracing::{error, warn, debug};
|
||||
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::error;
|
||||
use crate::error::DeviceError;
|
||||
use crate::mqtt::{OnMqtt, RemoteMessage, RemoteAction};
|
||||
use crate::presence::OnPresence;
|
||||
|
||||
@@ -21,16 +21,13 @@ pub struct AudioSetup {
|
||||
}
|
||||
|
||||
impl AudioSetup {
|
||||
pub async fn build(identifier: &str, mqtt: MqttDeviceConfig, mixer: DeviceBox, speakers: DeviceBox, client: AsyncClient) -> error::Result<Self> {
|
||||
pub async fn build(identifier: &str, mqtt: MqttDeviceConfig, mixer: DeviceBox, speakers: DeviceBox, client: AsyncClient) -> Result<Self, DeviceError> {
|
||||
// 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")))?,
|
||||
};
|
||||
let mixer = AsOnOff::consume(mixer)
|
||||
.ok_or_else(|| DeviceError::OnOffExpected(identifier.to_owned() + ".mixer"))?;
|
||||
|
||||
let speakers = AsOnOff::consume(speakers)
|
||||
.ok_or_else(|| DeviceError::OnOffExpected(identifier.to_owned() + ".speakers"))?;
|
||||
|
||||
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await?;
|
||||
|
||||
|
||||
@@ -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, error};
|
||||
use crate::{config::{MqttDeviceConfig, PresenceDeviceConfig}, mqtt::{OnMqtt, ContactMessage, PresenceMessage}, presence::OnPresence, error::DeviceError};
|
||||
|
||||
use super::Device;
|
||||
|
||||
@@ -22,7 +22,7 @@ pub struct ContactSensor {
|
||||
}
|
||||
|
||||
impl ContactSensor {
|
||||
pub async fn build(identifier: &str, mqtt: MqttDeviceConfig, presence: Option<PresenceDeviceConfig>, client: AsyncClient) -> error::Result<Self> {
|
||||
pub async fn build(identifier: &str, mqtt: MqttDeviceConfig, presence: Option<PresenceDeviceConfig>, client: AsyncClient) -> Result<Self, DeviceError> {
|
||||
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await?;
|
||||
|
||||
Ok(Self {
|
||||
|
||||
@@ -9,7 +9,7 @@ use pollster::FutureExt as _;
|
||||
|
||||
use crate::config::{KettleConfig, InfoConfig, MqttDeviceConfig};
|
||||
use crate::devices::Device;
|
||||
use crate::error;
|
||||
use crate::error::DeviceError;
|
||||
use crate::mqtt::{OnMqtt, OnOffMessage};
|
||||
use crate::presence::OnPresence;
|
||||
|
||||
@@ -26,7 +26,7 @@ pub struct IkeaOutlet {
|
||||
}
|
||||
|
||||
impl IkeaOutlet {
|
||||
pub async fn build(identifier: &str, info: InfoConfig, mqtt: MqttDeviceConfig, kettle: Option<KettleConfig>, client: AsyncClient) -> error::Result<Self> {
|
||||
pub async fn build(identifier: &str, info: InfoConfig, mqtt: MqttDeviceConfig, kettle: Option<KettleConfig>, client: AsyncClient) -> Result<Self, DeviceError> {
|
||||
// @TODO Handle potential errors here
|
||||
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await?;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use std::{net::{SocketAddr, Ipv4Addr, TcpStream}, io::{Write, Read}};
|
||||
use std::{net::{SocketAddr, Ipv4Addr, TcpStream}, io::{Write, Read}, str::Utf8Error};
|
||||
|
||||
use thiserror::Error;
|
||||
use bytes::{Buf, BufMut};
|
||||
use google_home::{traits, errors::{self, DeviceError}};
|
||||
use serde::{Serialize, Deserialize};
|
||||
@@ -89,9 +90,9 @@ struct ErrorCode {
|
||||
}
|
||||
|
||||
impl ErrorCode {
|
||||
fn ok(&self) -> Result<(), anyhow::Error> {
|
||||
fn ok(&self) -> Result<(), ResponseError> {
|
||||
if self.err_code != 0 {
|
||||
Err(anyhow::anyhow!("Error code: {}", self.err_code))
|
||||
Err(ResponseError::ErrorCode(self.err_code))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
@@ -122,28 +123,55 @@ struct Response {
|
||||
system: ResponseSystem,
|
||||
}
|
||||
|
||||
// @TODO Improve this error
|
||||
#[derive(Debug, Error)]
|
||||
enum ResponseError {
|
||||
#[error("Expected a minimum data length of 4")]
|
||||
ToShort,
|
||||
#[error("No sysinfo found in response")]
|
||||
SysinfoNotFound,
|
||||
#[error("No relay_state not found in response")]
|
||||
RelayStateNotFound,
|
||||
#[error("Error code: {0}")]
|
||||
ErrorCode(isize),
|
||||
#[error(transparent)]
|
||||
Other(#[from] Box<dyn std::error::Error>),
|
||||
}
|
||||
|
||||
impl From<Utf8Error> for ResponseError {
|
||||
fn from(err: Utf8Error) -> Self {
|
||||
ResponseError::Other(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for ResponseError {
|
||||
fn from(err: serde_json::Error) -> Self {
|
||||
ResponseError::Other(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl Response {
|
||||
fn get_current_relay_state(&self) -> Result<bool, anyhow::Error> {
|
||||
fn get_current_relay_state(&self) -> Result<bool, ResponseError> {
|
||||
if let Some(sysinfo) = &self.system.get_sysinfo {
|
||||
return sysinfo.err_code.ok()
|
||||
.map(|_| sysinfo.relay_state == 1);
|
||||
}
|
||||
|
||||
return Err(anyhow::anyhow!("No sysinfo found in response"));
|
||||
return Err(ResponseError::SysinfoNotFound);
|
||||
}
|
||||
|
||||
fn check_set_relay_success(&self) -> Result<(), anyhow::Error> {
|
||||
fn check_set_relay_success(&self) -> Result<(), ResponseError> {
|
||||
if let Some(set_relay_state) = &self.system.set_relay_state {
|
||||
return set_relay_state.err_code.ok();
|
||||
}
|
||||
|
||||
return Err(anyhow::anyhow!("No relay_state found in response"));
|
||||
return Err(ResponseError::RelayStateNotFound);
|
||||
}
|
||||
|
||||
fn decrypt(mut data: bytes::Bytes) -> Result<Self, anyhow::Error> {
|
||||
fn decrypt(mut data: bytes::Bytes) -> Result<Self, ResponseError> {
|
||||
let mut key: u8 = 171;
|
||||
if data.len() < 4 {
|
||||
return Err(anyhow::anyhow!("Expected a minimun data length of 4"));
|
||||
return Err(ResponseError::ToShort.into());
|
||||
}
|
||||
|
||||
let length = data.get_u32();
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
use async_trait::async_trait;
|
||||
use google_home::{GoogleHomeDevice, types::Type, device, traits::{self, Scene}, errors::{ErrorCode, DeviceError}};
|
||||
use google_home::{GoogleHomeDevice, types::Type, device, traits::{self, Scene}, errors::ErrorCode};
|
||||
use tracing::{debug, error};
|
||||
use rumqttc::{AsyncClient, Publish, matches};
|
||||
use pollster::FutureExt as _;
|
||||
use eui48::MacAddress;
|
||||
|
||||
use crate::{config::{InfoConfig, MqttDeviceConfig}, mqtt::{OnMqtt, ActivateMessage}, error};
|
||||
use crate::{config::{InfoConfig, MqttDeviceConfig}, mqtt::{OnMqtt, ActivateMessage}, error::DeviceError};
|
||||
|
||||
use super::Device;
|
||||
|
||||
@@ -18,7 +18,7 @@ pub struct WakeOnLAN {
|
||||
}
|
||||
|
||||
impl WakeOnLAN {
|
||||
pub async fn build(identifier: &str, info: InfoConfig, mqtt: MqttDeviceConfig, mac_address: MacAddress, client: AsyncClient) -> error::Result<Self> {
|
||||
pub async fn build(identifier: &str, info: InfoConfig, mqtt: MqttDeviceConfig, mac_address: MacAddress, client: AsyncClient) -> Result<Self, DeviceError> {
|
||||
// @TODO Handle potential errors here
|
||||
client.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce).await?;
|
||||
|
||||
@@ -89,7 +89,7 @@ impl traits::Scene for WakeOnLAN {
|
||||
Ok(res) => res,
|
||||
Err(err) => {
|
||||
error!(id, "Failed to call webhook: {err}");
|
||||
return Err(DeviceError::TransientError.into());
|
||||
return Err(google_home::errors::DeviceError::TransientError.into());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -102,7 +102,7 @@ impl traits::Scene for WakeOnLAN {
|
||||
} else {
|
||||
debug!(id = self.identifier, "Trying to deactive computer, this is not currently supported");
|
||||
// We do not support deactivating this scene
|
||||
Err(ErrorCode::DeviceError(DeviceError::ActionNotAvailable))
|
||||
Err(ErrorCode::DeviceError(google_home::errors::DeviceError::ActionNotAvailable))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user