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