Moved most config structs to be in the same file as what they are for
This commit is contained in:
@@ -1,16 +1,25 @@
|
||||
use async_trait::async_trait;
|
||||
use google_home::traits;
|
||||
use tracing::{debug, error, warn};
|
||||
use rumqttc::AsyncClient;
|
||||
use serde::Deserialize;
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::error::DeviceError;
|
||||
use crate::config::{self, MqttDeviceConfig};
|
||||
use crate::error::DeviceCreateError;
|
||||
use crate::mqtt::{OnMqtt, RemoteAction, RemoteMessage};
|
||||
use crate::presence::OnPresence;
|
||||
|
||||
use super::{As, Device};
|
||||
|
||||
// TODO: Ideally we store am Arc to the childern devices,
|
||||
// that way they hook into everything just like all other devices
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct AudioSetupConfig {
|
||||
#[serde(flatten)]
|
||||
mqtt: MqttDeviceConfig,
|
||||
mixer: Box<config::Device>,
|
||||
speakers: Box<config::Device>,
|
||||
}
|
||||
|
||||
// TODO: We need a better way to store the children devices
|
||||
#[derive(Debug)]
|
||||
pub struct AudioSetup {
|
||||
identifier: String,
|
||||
@@ -20,22 +29,28 @@ pub struct AudioSetup {
|
||||
}
|
||||
|
||||
impl AudioSetup {
|
||||
pub async fn build(
|
||||
pub fn create(
|
||||
identifier: &str,
|
||||
mqtt: MqttDeviceConfig,
|
||||
mixer: Box<dyn Device>,
|
||||
speakers: Box<dyn Device>,
|
||||
) -> Result<Self, DeviceError> {
|
||||
// We expect the children devices to implement the OnOff trait
|
||||
let mixer_id = mixer.get_id().to_owned();
|
||||
let mixer = As::consume(mixer).ok_or(DeviceError::OnOffExpected(mixer_id))?;
|
||||
config: AudioSetupConfig,
|
||||
client: AsyncClient,
|
||||
// We only need to pass this in because constructing children
|
||||
presence_topic: &str, // Not a big fan of passing in the global config
|
||||
) -> Result<Self, DeviceCreateError> {
|
||||
trace!(id = identifier, "Setting up AudioSetup");
|
||||
|
||||
let speakers_id = speakers.get_id().to_owned();
|
||||
let speakers = As::consume(speakers).ok_or(DeviceError::OnOffExpected(speakers_id))?;
|
||||
// Create the child devices
|
||||
let mixer_id = format!("{}.mixer", identifier);
|
||||
let mixer = (*config.mixer).create(&mixer_id, client.clone(), presence_topic)?;
|
||||
let mixer = As::consume(mixer).ok_or(DeviceCreateError::OnOffExpected(mixer_id))?;
|
||||
|
||||
let speakers_id = format!("{}.speakers", identifier);
|
||||
let speakers = (*config.speakers).create(&speakers_id, client, presence_topic)?;
|
||||
let speakers =
|
||||
As::consume(speakers).ok_or(DeviceCreateError::OnOffExpected(speakers_id))?;
|
||||
|
||||
Ok(Self {
|
||||
identifier: identifier.to_owned(),
|
||||
mqtt,
|
||||
mqtt: config.mqtt,
|
||||
mixer,
|
||||
speakers,
|
||||
})
|
||||
|
||||
@@ -1,18 +1,62 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use rumqttc::AsyncClient;
|
||||
use rumqttc::{has_wildcards, AsyncClient};
|
||||
use serde::Deserialize;
|
||||
use tokio::task::JoinHandle;
|
||||
use tracing::{debug, error, warn};
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use crate::{
|
||||
config::{MqttDeviceConfig, PresenceDeviceConfig},
|
||||
config::MqttDeviceConfig,
|
||||
error::{DeviceCreateError, MissingWildcard},
|
||||
mqtt::{ContactMessage, OnMqtt, PresenceMessage},
|
||||
presence::OnPresence,
|
||||
};
|
||||
|
||||
use super::Device;
|
||||
|
||||
// NOTE: If we add more presence devices we might need to move this out of here
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct PresenceDeviceConfig {
|
||||
#[serde(flatten)]
|
||||
pub mqtt: Option<MqttDeviceConfig>,
|
||||
pub timeout: u64, // Timeout in seconds
|
||||
}
|
||||
|
||||
impl PresenceDeviceConfig {
|
||||
/// Set the mqtt topic to an appropriate value if it is not already set
|
||||
fn generate_topic(
|
||||
mut self,
|
||||
class: &str,
|
||||
identifier: &str,
|
||||
presence_topic: &str,
|
||||
) -> Result<PresenceDeviceConfig, MissingWildcard> {
|
||||
if self.mqtt.is_none() {
|
||||
if !has_wildcards(presence_topic) {
|
||||
return Err(MissingWildcard::new(presence_topic));
|
||||
}
|
||||
|
||||
// TODO: This is not perfect, if the topic is some/+/thing/# this will fail
|
||||
let offset = presence_topic
|
||||
.find('+')
|
||||
.or(presence_topic.find('#'))
|
||||
.unwrap();
|
||||
let topic = format!("{}/{class}/{identifier}", &presence_topic[..offset - 1]);
|
||||
trace!("Setting presence mqtt topic: {topic}");
|
||||
self.mqtt = Some(MqttDeviceConfig { topic });
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct ContactSensorConfig {
|
||||
#[serde(flatten)]
|
||||
mqtt: MqttDeviceConfig,
|
||||
presence: Option<PresenceDeviceConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ContactSensor {
|
||||
identifier: String,
|
||||
@@ -26,21 +70,28 @@ pub struct ContactSensor {
|
||||
}
|
||||
|
||||
impl ContactSensor {
|
||||
pub fn new(
|
||||
pub fn create(
|
||||
identifier: &str,
|
||||
mqtt: MqttDeviceConfig,
|
||||
presence: Option<PresenceDeviceConfig>,
|
||||
config: ContactSensorConfig,
|
||||
client: AsyncClient,
|
||||
) -> Self {
|
||||
Self {
|
||||
presence_topic: &str,
|
||||
) -> Result<Self, DeviceCreateError> {
|
||||
trace!(id = identifier, "Setting up ContactSensor");
|
||||
|
||||
let presence = config
|
||||
.presence
|
||||
.map(|p| p.generate_topic("contact", identifier, presence_topic))
|
||||
.transpose()?;
|
||||
|
||||
Ok(Self {
|
||||
identifier: identifier.to_owned(),
|
||||
mqtt,
|
||||
mqtt: config.mqtt,
|
||||
presence,
|
||||
client,
|
||||
overall_presence: false,
|
||||
is_closed: true,
|
||||
handle: None,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,15 +8,39 @@ use google_home::{
|
||||
};
|
||||
use pollster::FutureExt as _;
|
||||
use rumqttc::{AsyncClient, Publish};
|
||||
use serde::Deserialize;
|
||||
use std::time::Duration;
|
||||
use tokio::task::JoinHandle;
|
||||
use tracing::{debug, error, warn};
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use crate::config::{InfoConfig, MqttDeviceConfig, OutletType};
|
||||
use crate::config::{InfoConfig, MqttDeviceConfig};
|
||||
use crate::devices::Device;
|
||||
use crate::error::DeviceCreateError;
|
||||
use crate::mqtt::{OnMqtt, OnOffMessage};
|
||||
use crate::presence::OnPresence;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Copy)]
|
||||
pub enum OutletType {
|
||||
Outlet,
|
||||
Kettle,
|
||||
Charger,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct IkeaOutletConfig {
|
||||
#[serde(flatten)]
|
||||
info: InfoConfig,
|
||||
#[serde(flatten)]
|
||||
mqtt: MqttDeviceConfig,
|
||||
#[serde(default = "default_outlet_type")]
|
||||
outlet_type: OutletType,
|
||||
timeout: Option<u64>, // Timeout in seconds
|
||||
}
|
||||
|
||||
fn default_outlet_type() -> OutletType {
|
||||
OutletType::Outlet
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IkeaOutlet {
|
||||
identifier: String,
|
||||
@@ -31,24 +55,28 @@ pub struct IkeaOutlet {
|
||||
}
|
||||
|
||||
impl IkeaOutlet {
|
||||
pub fn new(
|
||||
pub fn create(
|
||||
identifier: &str,
|
||||
info: InfoConfig,
|
||||
mqtt: MqttDeviceConfig,
|
||||
outlet_type: OutletType,
|
||||
timeout: Option<u64>,
|
||||
config: IkeaOutletConfig,
|
||||
client: AsyncClient,
|
||||
) -> Self {
|
||||
Self {
|
||||
) -> Result<Self, DeviceCreateError> {
|
||||
trace!(
|
||||
id = identifier,
|
||||
name = config.info.name,
|
||||
room = config.info.room,
|
||||
"Setting up IkeaOutlet"
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
identifier: identifier.to_owned(),
|
||||
info,
|
||||
mqtt,
|
||||
outlet_type,
|
||||
timeout,
|
||||
info: config.info,
|
||||
mqtt: config.mqtt,
|
||||
outlet_type: config.outlet_type,
|
||||
timeout: config.timeout,
|
||||
client,
|
||||
last_known_state: false,
|
||||
handle: None,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,9 +11,17 @@ use google_home::{
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::error::DeviceCreateError;
|
||||
|
||||
use super::Device;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct KasaOutletConfig {
|
||||
ip: Ipv4Addr,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct KasaOutlet {
|
||||
identifier: String,
|
||||
@@ -21,11 +29,13 @@ pub struct KasaOutlet {
|
||||
}
|
||||
|
||||
impl KasaOutlet {
|
||||
pub fn new(identifier: &str, ip: Ipv4Addr) -> Self {
|
||||
Self {
|
||||
pub fn create(identifier: &str, config: KasaOutletConfig) -> Result<Self, DeviceCreateError> {
|
||||
trace!(id = identifier, "Setting up KasaOutlet");
|
||||
|
||||
Ok(Self {
|
||||
identifier: identifier.to_owned(),
|
||||
addr: (ip, 9999).into(),
|
||||
}
|
||||
addr: (config.ip, 9999).into(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,15 +10,32 @@ use google_home::{
|
||||
GoogleHomeDevice,
|
||||
};
|
||||
use rumqttc::Publish;
|
||||
use tracing::{debug, error};
|
||||
use serde::Deserialize;
|
||||
use tracing::{debug, error, trace};
|
||||
|
||||
use crate::{
|
||||
config::{InfoConfig, MqttDeviceConfig},
|
||||
error::DeviceCreateError,
|
||||
mqtt::{ActivateMessage, OnMqtt},
|
||||
};
|
||||
|
||||
use super::Device;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct WakeOnLANConfig {
|
||||
#[serde(flatten)]
|
||||
info: InfoConfig,
|
||||
#[serde(flatten)]
|
||||
mqtt: MqttDeviceConfig,
|
||||
mac_address: MacAddress,
|
||||
#[serde(default = "default_broadcast_ip")]
|
||||
broadcast_ip: Ipv4Addr,
|
||||
}
|
||||
|
||||
fn default_broadcast_ip() -> Ipv4Addr {
|
||||
Ipv4Addr::new(255, 255, 255, 255)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WakeOnLAN {
|
||||
identifier: String,
|
||||
@@ -29,20 +46,21 @@ pub struct WakeOnLAN {
|
||||
}
|
||||
|
||||
impl WakeOnLAN {
|
||||
pub fn new(
|
||||
identifier: &str,
|
||||
info: InfoConfig,
|
||||
mqtt: MqttDeviceConfig,
|
||||
mac_address: MacAddress,
|
||||
broadcast_ip: Ipv4Addr,
|
||||
) -> Self {
|
||||
Self {
|
||||
pub fn create(identifier: &str, config: WakeOnLANConfig) -> Result<Self, DeviceCreateError> {
|
||||
trace!(
|
||||
id = identifier,
|
||||
name = config.info.name,
|
||||
room = config.info.room,
|
||||
"Setting up WakeOnLAN"
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
identifier: identifier.to_owned(),
|
||||
info,
|
||||
mqtt,
|
||||
mac_address,
|
||||
broadcast_ip,
|
||||
}
|
||||
info: config.info,
|
||||
mqtt: config.mqtt,
|
||||
mac_address: config.mac_address,
|
||||
broadcast_ip: config.broadcast_ip,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user