Devices now keep type in lua
This commit is contained in:
parent
b0467b8012
commit
d11e79cdfa
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -106,6 +106,7 @@ dependencies = [
|
|||
"futures",
|
||||
"google_home",
|
||||
"hostname",
|
||||
"impls",
|
||||
"indexmap 2.2.6",
|
||||
"mlua",
|
||||
"once_cell",
|
||||
|
@ -877,6 +878,12 @@ dependencies = [
|
|||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "impls"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a46645bbd70538861a90d0f26c31537cdf1e44aae99a794fb75a664b70951bc"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.9.3"
|
||||
|
|
|
@ -56,6 +56,7 @@ hostname = "0.4.0"
|
|||
tokio-util = { version = "0.7.11", features = ["full"] }
|
||||
uuid = "1.8.0"
|
||||
dyn-clone = "1.0.17"
|
||||
impls = "1.0.3"
|
||||
|
||||
[patch.crates-io]
|
||||
wakey = { git = "https://git.huizinga.dev/Dreaded_X/wakey" }
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use futures::future::join_all;
|
||||
use futures::Future;
|
||||
use google_home::traits::OnOff;
|
||||
use mlua::FromLua;
|
||||
use tokio::sync::{RwLock, RwLockReadGuard};
|
||||
use tokio_cron_scheduler::{Job, JobScheduler};
|
||||
use tokio_util::task::LocalPoolHandle;
|
||||
|
@ -16,37 +13,6 @@ use crate::devices::Device;
|
|||
use crate::event::{Event, EventChannel, OnDarkness, OnMqtt, OnNotification, OnPresence};
|
||||
use crate::LUA;
|
||||
|
||||
#[derive(Debug, FromLua, Clone)]
|
||||
pub struct WrappedDevice(Box<dyn Device>);
|
||||
|
||||
impl WrappedDevice {
|
||||
pub fn new(device: impl Device + 'static) -> Self {
|
||||
Self(Box::new(device))
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for WrappedDevice {
|
||||
type Target = Box<dyn Device>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl mlua::UserData for WrappedDevice {
|
||||
fn add_methods<'lua, M: mlua::prelude::LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_async_method("get_id", |_lua, this, _: ()| async { Ok(this.get_id()) });
|
||||
|
||||
methods.add_async_method("set_on", |_lua, this, on: bool| async move {
|
||||
if let Some(device) = this.cast() as Option<&dyn OnOff> {
|
||||
device.set_on(on).await.unwrap()
|
||||
};
|
||||
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub type DeviceMap = HashMap<String, Box<dyn Device>>;
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -195,8 +161,8 @@ fn run_schedule(
|
|||
|
||||
impl mlua::UserData for DeviceManager {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_async_method("add", |_lua, this, device: WrappedDevice| async move {
|
||||
this.add(device.0).await;
|
||||
methods.add_async_method("add", |_lua, this, device: Box<dyn Device>| async move {
|
||||
this.add(device).await;
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
|
|
@ -5,7 +5,6 @@ use tracing::{debug, error, trace, warn};
|
|||
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::device_manager::WrappedDevice;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::{OnMqtt, OnPresence};
|
||||
use crate::messages::{RemoteAction, RemoteMessage};
|
||||
|
@ -17,9 +16,9 @@ pub struct Config {
|
|||
#[device_config(flatten)]
|
||||
pub mqtt: MqttDeviceConfig,
|
||||
#[device_config(from_lua)]
|
||||
pub mixer: WrappedDevice,
|
||||
pub mixer: Box<dyn Device>,
|
||||
#[device_config(from_lua)]
|
||||
pub speakers: WrappedDevice,
|
||||
pub speakers: Box<dyn Device>,
|
||||
#[device_config(from_lua)]
|
||||
pub client: WrappedAsyncClient,
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ use tracing::{debug, error, trace, warn};
|
|||
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::device_manager::WrappedDevice;
|
||||
use crate::devices::DEFAULT_PRESENCE;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::{OnMqtt, OnPresence};
|
||||
|
@ -30,7 +29,7 @@ pub struct PresenceDeviceConfig {
|
|||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct TriggerConfig {
|
||||
#[device_config(from_lua)]
|
||||
pub devices: Vec<WrappedDevice>,
|
||||
pub devices: Vec<Box<dyn Device>>,
|
||||
#[device_config(default, with(|t: Option<_>| t.map(Duration::from_secs)))]
|
||||
pub timeout: Option<Duration>,
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ use async_trait::async_trait;
|
|||
use automation_cast::Cast;
|
||||
use dyn_clone::DynClone;
|
||||
use google_home::traits::OnOff;
|
||||
use mlua::AnyUserDataExt;
|
||||
|
||||
pub use self::air_filter::AirFilter;
|
||||
pub use self::audio_setup::AudioSetup;
|
||||
|
@ -53,37 +54,61 @@ macro_rules! register_device {
|
|||
}
|
||||
|
||||
macro_rules! impl_device {
|
||||
($lua:expr, $device:ty) => {
|
||||
($device:ty) => {
|
||||
impl mlua::UserData for $device {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_async_function("new", |lua, config: mlua::Value| async {
|
||||
let config = mlua::FromLua::from_lua(config, lua)?;
|
||||
|
||||
// TODO: Using crate:: could cause issues
|
||||
methods.add_async_function("new", |_lua, config| async {
|
||||
let device: $device = crate::devices::LuaDeviceCreate::create(config)
|
||||
.await
|
||||
.map_err(mlua::ExternalError::into_lua_err)?;
|
||||
|
||||
Ok(crate::device_manager::WrappedDevice::new(device))
|
||||
Ok(device)
|
||||
});
|
||||
|
||||
methods.add_method("__box", |_lua, this, _: ()| {
|
||||
let b: Box<dyn Device> = Box::new(this.clone());
|
||||
Ok(b)
|
||||
});
|
||||
|
||||
methods.add_async_method("get_id", |_lua, this, _: ()| async { Ok(this.get_id()) });
|
||||
|
||||
if impls::impls!($device: OnOff) {
|
||||
methods.add_async_method("set_on", |_lua, this, on: bool| async move {
|
||||
(this.cast() as Option<&dyn OnOff>)
|
||||
.unwrap()
|
||||
.set_on(on)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
||||
methods.add_async_method("is_on", |_lua, this, _: ()| async move {
|
||||
Ok((this.cast() as Option<&dyn OnOff>)
|
||||
.unwrap()
|
||||
.on()
|
||||
.await
|
||||
.unwrap())
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_device!(lua, AirFilter);
|
||||
impl_device!(lua, AudioSetup);
|
||||
impl_device!(lua, ContactSensor);
|
||||
impl_device!(lua, DebugBridge);
|
||||
impl_device!(lua, HueBridge);
|
||||
impl_device!(lua, HueGroup);
|
||||
impl_device!(lua, IkeaOutlet);
|
||||
impl_device!(lua, KasaOutlet);
|
||||
impl_device!(lua, LightSensor);
|
||||
impl_device!(lua, Ntfy);
|
||||
impl_device!(lua, Presence);
|
||||
impl_device!(lua, WakeOnLAN);
|
||||
impl_device!(lua, Washer);
|
||||
impl_device!(AirFilter);
|
||||
impl_device!(AudioSetup);
|
||||
impl_device!(ContactSensor);
|
||||
impl_device!(DebugBridge);
|
||||
impl_device!(HueBridge);
|
||||
impl_device!(HueGroup);
|
||||
impl_device!(IkeaOutlet);
|
||||
impl_device!(KasaOutlet);
|
||||
impl_device!(LightSensor);
|
||||
impl_device!(Ntfy);
|
||||
impl_device!(Presence);
|
||||
impl_device!(WakeOnLAN);
|
||||
impl_device!(Washer);
|
||||
|
||||
pub fn register_with_lua(lua: &mlua::Lua) -> mlua::Result<()> {
|
||||
register_device!(lua, AirFilter);
|
||||
|
@ -120,4 +145,23 @@ pub trait Device:
|
|||
fn get_id(&self) -> String;
|
||||
}
|
||||
|
||||
impl<'lua> mlua::FromLua<'lua> for Box<dyn Device> {
|
||||
fn from_lua(value: mlua::Value<'lua>, _lua: &'lua mlua::Lua) -> mlua::Result<Self> {
|
||||
match value {
|
||||
mlua::Value::UserData(ud) => {
|
||||
let ud = if ud.is::<Box<dyn Device>>() {
|
||||
ud
|
||||
} else {
|
||||
ud.call_method::<_, mlua::AnyUserData>("__box", ())?
|
||||
};
|
||||
|
||||
let b = ud.borrow::<Self>()?.clone();
|
||||
Ok(b)
|
||||
}
|
||||
_ => Err(mlua::Error::RuntimeError("Expected user data".into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl mlua::UserData for Box<dyn Device> {}
|
||||
|
||||
dyn_clone::clone_trait_object!(Device);
|
||||
|
|
Loading…
Reference in New Issue
Block a user