Improved impl_cast and made all traits Sync + Send + 'static
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -12,7 +12,7 @@ use serde::Deserialize;
|
||||
use tracing::{debug, trace};
|
||||
|
||||
use crate::{
|
||||
devices::{self, AudioSetup, ContactSensor, DeviceBox, IkeaOutlet, KasaOutlet, WakeOnLAN},
|
||||
devices::{self, AudioSetup, ContactSensor, IkeaOutlet, KasaOutlet, WakeOnLAN},
|
||||
error::{ConfigParseError, DeviceCreationError, MissingEnv, MissingWildcard},
|
||||
};
|
||||
|
||||
@@ -255,10 +255,10 @@ impl Config {
|
||||
// Quick helper function to box up the devices,
|
||||
// passing in Box::new would be ideal, however the return type is incorrect
|
||||
// Maybe there is a better way to solve this?
|
||||
fn device_box<T: devices::Device + 'static>(device: T) -> DeviceBox {
|
||||
let a: DeviceBox = Box::new(device);
|
||||
a
|
||||
}
|
||||
// fn device_box<T: devices::Device>(device: T) -> DeviceBox {
|
||||
// let a: DeviceBox = Box::new(device);
|
||||
// a
|
||||
// }
|
||||
|
||||
impl Device {
|
||||
#[async_recursion]
|
||||
@@ -267,8 +267,8 @@ impl Device {
|
||||
identifier: &str,
|
||||
config: &Config,
|
||||
client: AsyncClient,
|
||||
) -> Result<DeviceBox, DeviceCreationError> {
|
||||
let device = match self {
|
||||
) -> Result<Box<dyn devices::Device>, DeviceCreationError> {
|
||||
let device: Box<dyn devices::Device> = match self {
|
||||
Device::IkeaOutlet {
|
||||
info,
|
||||
mqtt,
|
||||
@@ -283,7 +283,7 @@ impl Device {
|
||||
);
|
||||
IkeaOutlet::build(identifier, info, mqtt, outlet_type, timeout, client)
|
||||
.await
|
||||
.map(device_box)?
|
||||
.map(Box::new)?
|
||||
}
|
||||
Device::WakeOnLAN {
|
||||
info,
|
||||
@@ -299,11 +299,11 @@ impl Device {
|
||||
);
|
||||
WakeOnLAN::build(identifier, info, mqtt, mac_address, broadcast_ip, client)
|
||||
.await
|
||||
.map(device_box)?
|
||||
.map(Box::new)?
|
||||
}
|
||||
Device::KasaOutlet { ip } => {
|
||||
trace!(id = identifier, "KasaOutlet [{}]", identifier);
|
||||
device_box(KasaOutlet::new(identifier, ip))
|
||||
Box::new(KasaOutlet::new(identifier, ip))
|
||||
}
|
||||
Device::AudioSetup {
|
||||
mqtt,
|
||||
@@ -321,7 +321,7 @@ impl Device {
|
||||
|
||||
AudioSetup::build(identifier, mqtt, mixer, speakers, client)
|
||||
.await
|
||||
.map(device_box)?
|
||||
.map(Box::new)?
|
||||
}
|
||||
Device::ContactSensor { mqtt, presence } => {
|
||||
trace!(id = identifier, "ContactSensor [{}]", identifier);
|
||||
@@ -331,7 +331,7 @@ impl Device {
|
||||
|
||||
ContactSensor::build(identifier, mqtt, presence, client)
|
||||
.await
|
||||
.map(device_box)?
|
||||
.map(Box::new)?
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ use crate::{
|
||||
presence::{self, OnPresence},
|
||||
};
|
||||
|
||||
impl_cast::impl_setup!();
|
||||
impl_cast::impl_cast!(Device, OnMqtt);
|
||||
impl_cast::impl_cast!(Device, OnPresence);
|
||||
impl_cast::impl_cast!(Device, OnDarkness);
|
||||
@@ -32,14 +33,15 @@ impl_cast::impl_cast!(Device, GoogleHomeDevice);
|
||||
impl_cast::impl_cast!(Device, OnOff);
|
||||
|
||||
pub trait Device:
|
||||
AsGoogleHomeDevice
|
||||
+ AsOnMqtt
|
||||
+ AsOnPresence
|
||||
+ AsOnDarkness
|
||||
+ AsOnOff
|
||||
As<dyn GoogleHomeDevice>
|
||||
+ As<dyn OnMqtt>
|
||||
+ As<dyn OnPresence>
|
||||
+ As<dyn OnDarkness>
|
||||
+ As<dyn OnOff>
|
||||
+ std::fmt::Debug
|
||||
+ Sync
|
||||
+ Send
|
||||
+ 'static
|
||||
{
|
||||
fn get_id(&self) -> &str;
|
||||
}
|
||||
@@ -47,7 +49,7 @@ pub trait Device:
|
||||
// TODO: Add an inner type that we can wrap with Arc<RwLock<>> to make this type a little bit nicer
|
||||
// to work with
|
||||
struct Devices {
|
||||
devices: HashMap<String, DeviceBox>,
|
||||
devices: HashMap<String, Box<dyn Device>>,
|
||||
}
|
||||
|
||||
macro_rules! get_cast {
|
||||
@@ -57,7 +59,7 @@ macro_rules! get_cast {
|
||||
self.devices
|
||||
.iter_mut()
|
||||
.filter_map(|(id, device)| {
|
||||
[< As $trait >]::cast_mut(device.as_mut())
|
||||
As::<dyn $trait>::cast_mut(device.as_mut())
|
||||
.map(|listener| (id.as_str(), listener))
|
||||
}).collect()
|
||||
}
|
||||
@@ -73,13 +75,11 @@ pub enum Command {
|
||||
tx: oneshot::Sender<Result<google_home::Response, FullfillmentError>>,
|
||||
},
|
||||
AddDevice {
|
||||
device: DeviceBox,
|
||||
device: Box<dyn Device>,
|
||||
tx: oneshot::Sender<()>,
|
||||
},
|
||||
}
|
||||
|
||||
pub type DeviceBox = Box<dyn Device>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct DevicesHandle {
|
||||
tx: mpsc::Sender<Command>,
|
||||
@@ -113,7 +113,7 @@ impl DevicesHandle {
|
||||
Ok(rx.await??)
|
||||
}
|
||||
|
||||
pub async fn add_device(&self, device: DeviceBox) -> Result<(), DevicesError> {
|
||||
pub async fn add_device(&self, device: Box<dyn Device>) -> Result<(), DevicesError> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.tx.send(Command::AddDevice { device, tx }).await?;
|
||||
Ok(rx.await?)
|
||||
@@ -176,7 +176,7 @@ impl Devices {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_device(&mut self, device: DeviceBox) {
|
||||
fn add_device(&mut self, device: Box<dyn Device>) {
|
||||
debug!(id = device.get_id(), "Adding device");
|
||||
self.devices.insert(device.get_id().to_owned(), device);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::error::DeviceError;
|
||||
use crate::mqtt::{OnMqtt, RemoteAction, RemoteMessage};
|
||||
use crate::presence::OnPresence;
|
||||
|
||||
use super::{AsOnOff, Device, DeviceBox};
|
||||
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
|
||||
@@ -16,25 +16,25 @@ use super::{AsOnOff, Device, DeviceBox};
|
||||
pub struct AudioSetup {
|
||||
identifier: String,
|
||||
mqtt: MqttDeviceConfig,
|
||||
mixer: Box<dyn traits::OnOff + Sync + Send>,
|
||||
speakers: Box<dyn traits::OnOff + Sync + Send>,
|
||||
mixer: Box<dyn traits::OnOff>,
|
||||
speakers: Box<dyn traits::OnOff>,
|
||||
}
|
||||
|
||||
impl AudioSetup {
|
||||
pub async fn build(
|
||||
identifier: &str,
|
||||
mqtt: MqttDeviceConfig,
|
||||
mixer: DeviceBox,
|
||||
speakers: DeviceBox,
|
||||
mixer: Box<dyn Device>,
|
||||
speakers: Box<dyn Device>,
|
||||
client: AsyncClient,
|
||||
) -> Result<Self, DeviceError> {
|
||||
// We expect the children devices to implement the OnOff trait
|
||||
let mixer_id = mixer.get_id().to_owned();
|
||||
let mixer = AsOnOff::consume(mixer).ok_or_else(|| DeviceError::OnOffExpected(mixer_id))?;
|
||||
let mixer = As::consume(mixer).ok_or_else(|| DeviceError::OnOffExpected(mixer_id))?;
|
||||
|
||||
let speakers_id = speakers.get_id().to_owned();
|
||||
let speakers =
|
||||
AsOnOff::consume(speakers).ok_or_else(|| DeviceError::OnOffExpected(speakers_id))?;
|
||||
As::consume(speakers).ok_or_else(|| DeviceError::OnOffExpected(speakers_id))?;
|
||||
|
||||
client
|
||||
.subscribe(mqtt.topic.clone(), rumqttc::QoS::AtLeastOnce)
|
||||
|
||||
@@ -10,7 +10,7 @@ use crate::{
|
||||
};
|
||||
|
||||
#[async_trait]
|
||||
pub trait OnDarkness {
|
||||
pub trait OnDarkness: Sync + Send + 'static {
|
||||
async fn on_darkness(&mut self, dark: bool);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ use rumqttc::{Event, EventLoop, Incoming, Publish};
|
||||
use tokio::sync::broadcast;
|
||||
|
||||
#[async_trait]
|
||||
pub trait OnMqtt {
|
||||
pub trait OnMqtt: Sync + Send + 'static {
|
||||
async fn on_mqtt(&mut self, message: &Publish);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::{
|
||||
};
|
||||
|
||||
#[async_trait]
|
||||
pub trait OnPresence {
|
||||
pub trait OnPresence: Sync + Send + 'static {
|
||||
async fn on_presence(&mut self, presence: bool);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user