WIP: Lua action callback
This commit is contained in:
@@ -44,6 +44,17 @@ impl mlua::UserData for WrappedDevice {
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
||||
methods.add_async_method("is_on", |_lua, this, _: ()| async move {
|
||||
let device = this.0.read().await;
|
||||
let device = device.as_ref();
|
||||
|
||||
if let Some(device) = device.cast() as Option<&dyn OnOff> {
|
||||
return Ok(device.on().await.unwrap());
|
||||
};
|
||||
|
||||
Ok(false)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,8 +221,7 @@ impl mlua::UserData for DeviceManager {
|
||||
let uuid = this.scheduler.add(job).await.unwrap();
|
||||
|
||||
// Store the function in the registry
|
||||
lua.set_named_registry_value(uuid.to_string().as_str(), f)
|
||||
.unwrap();
|
||||
lua.set_named_registry_value(&uuid.to_string(), f).unwrap();
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@ use automation_macro::LuaDeviceConfig;
|
||||
use google_home::traits::OnOff;
|
||||
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use tokio::task::JoinHandle;
|
||||
use tokio_util::task::LocalPoolHandle;
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
@@ -17,6 +18,7 @@ use crate::event::{OnMqtt, OnPresence};
|
||||
use crate::messages::{ContactMessage, PresenceMessage};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
use crate::traits::Timeout;
|
||||
use crate::LUA;
|
||||
|
||||
// NOTE: If we add more presence devices we might need to move this out of here
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
@@ -35,6 +37,37 @@ pub struct TriggerConfig {
|
||||
pub timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct ActionCallback(uuid::Uuid);
|
||||
|
||||
impl<'lua> FromLua<'lua> for ActionCallback {
|
||||
fn from_lua(value: mlua::Value<'lua>, lua: &'lua mlua::Lua) -> mlua::Result<Self> {
|
||||
let uuid = uuid::Uuid::new_v4();
|
||||
lua.set_named_registry_value(&uuid.to_string(), value)?;
|
||||
|
||||
Ok(ActionCallback(uuid))
|
||||
}
|
||||
}
|
||||
|
||||
impl ActionCallback {
|
||||
async fn call(&self, closed: bool) {
|
||||
let pool = LocalPoolHandle::new(1);
|
||||
let uuid = self.0;
|
||||
|
||||
pool.spawn_pinned(move || async move {
|
||||
let lua = LUA.lock().await;
|
||||
let action: mlua::Value = lua.named_registry_value(&uuid.to_string())?;
|
||||
match action {
|
||||
mlua::Value::Function(f) => f.call_async::<_, ()>(closed).await,
|
||||
_ => todo!("Only functions are currently supported"),
|
||||
}
|
||||
})
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct Config {
|
||||
pub identifier: String,
|
||||
@@ -46,6 +79,8 @@ pub struct Config {
|
||||
pub trigger: Option<TriggerConfig>,
|
||||
#[device_config(from_lua)]
|
||||
pub client: WrappedAsyncClient,
|
||||
#[device_config(from_lua)]
|
||||
pub action: ActionCallback,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -152,6 +187,8 @@ impl OnMqtt for ContactSensor {
|
||||
debug!(id = self.get_id(), "Updating state to {is_closed}");
|
||||
self.state_mut().await.is_closed = is_closed;
|
||||
|
||||
self.config.action.call(self.is_closed).await;
|
||||
|
||||
if let Some(trigger) = &self.config.trigger {
|
||||
if !is_closed {
|
||||
for (light, previous) in trigger
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#![allow(incomplete_features)]
|
||||
#![feature(specialization)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(unboxed_closures)]
|
||||
|
||||
use once_cell::sync::Lazy;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
16
src/main.rs
16
src/main.rs
@@ -16,6 +16,7 @@ use dotenvy::dotenv;
|
||||
use google_home::{GoogleHome, Request, Response};
|
||||
use mlua::LuaSerdeExt;
|
||||
use rumqttc::AsyncClient;
|
||||
use tokio_util::task::LocalPoolHandle;
|
||||
use tracing::{debug, error, info, warn};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -96,6 +97,21 @@ async fn app() -> anyhow::Result<()> {
|
||||
automation.set("new_mqtt_client", new_mqtt_client)?;
|
||||
automation.set("device_manager", device_manager.clone())?;
|
||||
|
||||
let timeout = lua.create_function(|lua, (t, f): (u64, mlua::Function)| {
|
||||
let pool = LocalPoolHandle::new(1);
|
||||
let key = lua.create_registry_value(f).unwrap();
|
||||
pool.spawn_pinned(move || async move {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(t)).await;
|
||||
let lua = LUA.lock().await;
|
||||
let f: mlua::Function = lua.registry_value(&key).unwrap();
|
||||
f.call_async::<_, ()>(()).await.unwrap();
|
||||
lua.remove_registry_value(key).unwrap();
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})?;
|
||||
automation.set("timeout", timeout)?;
|
||||
|
||||
let util = lua.create_table()?;
|
||||
let get_env = lua.create_function(|_lua, name: String| {
|
||||
std::env::var(name).map_err(mlua::ExternalError::into_lua_err)
|
||||
|
||||
Reference in New Issue
Block a user