ActionCallback now always returns self and state can be anything serializable
This commit is contained in:
parent
eefb476d7f
commit
41d2af655b
|
@ -32,7 +32,7 @@ pub struct Config {
|
||||||
#[device_config(from_lua, default)]
|
#[device_config(from_lua, default)]
|
||||||
pub presence: Option<PresenceDeviceConfig>,
|
pub presence: Option<PresenceDeviceConfig>,
|
||||||
#[device_config(from_lua, default)]
|
#[device_config(from_lua, default)]
|
||||||
pub callback: ActionCallback<bool>,
|
pub callback: ActionCallback<ContactSensor, bool>,
|
||||||
#[device_config(from_lua)]
|
#[device_config(from_lua)]
|
||||||
pub client: WrappedAsyncClient,
|
pub client: WrappedAsyncClient,
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ impl OnMqtt for ContactSensor {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.config.callback.call(!is_closed).await;
|
self.config.callback.call(self, &!is_closed).await;
|
||||||
|
|
||||||
debug!(id = self.get_id(), "Updating state to {is_closed}");
|
debug!(id = self.get_id(), "Updating state to {is_closed}");
|
||||||
self.state_mut().await.is_closed = is_closed;
|
self.state_mut().await.is_closed = is_closed;
|
||||||
|
|
|
@ -21,10 +21,10 @@ pub struct Config {
|
||||||
pub client: WrappedAsyncClient,
|
pub client: WrappedAsyncClient,
|
||||||
|
|
||||||
#[device_config(from_lua, default)]
|
#[device_config(from_lua, default)]
|
||||||
pub left_callback: ActionCallback<()>,
|
pub left_callback: ActionCallback<HueSwitch, ()>,
|
||||||
|
|
||||||
#[device_config(from_lua, default)]
|
#[device_config(from_lua, default)]
|
||||||
pub right_callback: ActionCallback<()>,
|
pub right_callback: ActionCallback<HueSwitch, ()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -58,7 +58,7 @@ impl LuaDeviceCreate for HueSwitch {
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl OnMqtt for HueSwitch {
|
impl OnMqtt for HueSwitch {
|
||||||
async fn on_mqtt(&self, message: Publish) {
|
async fn on_mqtt(&self, message: Publish) {
|
||||||
// Check if the message is from the deviec itself or from a remote
|
// Check if the message is from the device itself or from a remote
|
||||||
if matches(&message.topic, &self.config.mqtt.topic) {
|
if matches(&message.topic, &self.config.mqtt.topic) {
|
||||||
let action = match serde_json::from_slice::<Zigbee929003017102>(&message.payload) {
|
let action = match serde_json::from_slice::<Zigbee929003017102>(&message.payload) {
|
||||||
Ok(message) => message.action,
|
Ok(message) => message.action,
|
||||||
|
@ -70,8 +70,12 @@ impl OnMqtt for HueSwitch {
|
||||||
debug!(id = Device::get_id(self), "Remote action = {:?}", action);
|
debug!(id = Device::get_id(self), "Remote action = {:?}", action);
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
Zigbee929003017102Action::LeftPress => self.config.left_callback.call(()).await,
|
Zigbee929003017102Action::LeftPress => {
|
||||||
Zigbee929003017102Action::RightPress => self.config.right_callback.call(()).await,
|
self.config.left_callback.call(self, &()).await
|
||||||
|
}
|
||||||
|
Zigbee929003017102Action::RightPress => {
|
||||||
|
self.config.right_callback.call(self, &()).await
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub struct Config {
|
||||||
pub outlet_type: OutletType,
|
pub outlet_type: OutletType,
|
||||||
|
|
||||||
#[device_config(from_lua, default)]
|
#[device_config(from_lua, default)]
|
||||||
pub callback: ActionCallback<(IkeaOutlet, bool)>,
|
pub callback: ActionCallback<IkeaOutlet, bool>,
|
||||||
|
|
||||||
#[device_config(from_lua)]
|
#[device_config(from_lua)]
|
||||||
pub client: WrappedAsyncClient,
|
pub client: WrappedAsyncClient,
|
||||||
|
@ -109,7 +109,7 @@ impl OnMqtt for IkeaOutlet {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.config.callback.call((self.clone(), state)).await;
|
self.config.callback.call(self, &state).await;
|
||||||
|
|
||||||
debug!(id = Device::get_id(self), "Updating state to {state}");
|
debug!(id = Device::get_id(self), "Updating state to {state}");
|
||||||
self.state_mut().await.last_known_state = state;
|
self.state_mut().await.last_known_state = state;
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub struct Config {
|
||||||
pub client: WrappedAsyncClient,
|
pub client: WrappedAsyncClient,
|
||||||
|
|
||||||
#[device_config(from_lua)]
|
#[device_config(from_lua)]
|
||||||
pub callback: ActionCallback<bool>,
|
pub callback: ActionCallback<IkeaRemote, bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -84,7 +84,7 @@ impl OnMqtt for IkeaRemote {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(on) = on {
|
if let Some(on) = on {
|
||||||
self.config.callback.call(on).await;
|
self.config.callback.call(self, &on).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use mlua::{FromLua, IntoLuaMulti};
|
use mlua::{FromLua, IntoLua, LuaSerdeExt};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct Internal {
|
struct Internal {
|
||||||
|
@ -9,21 +10,23 @@ struct Internal {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ActionCallback<T> {
|
pub struct ActionCallback<T, S> {
|
||||||
internal: Option<Internal>,
|
internal: Option<Internal>,
|
||||||
phantom: PhantomData<T>,
|
_this: PhantomData<T>,
|
||||||
|
_state: PhantomData<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Default for ActionCallback<T> {
|
impl<T, S> Default for ActionCallback<T, S> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
internal: None,
|
internal: None,
|
||||||
phantom: PhantomData::<T>,
|
_this: PhantomData::<T>,
|
||||||
|
_state: PhantomData::<S>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> FromLua for ActionCallback<T> {
|
impl<T, S> FromLua for ActionCallback<T, S> {
|
||||||
fn from_lua(value: mlua::Value, lua: &mlua::Lua) -> mlua::Result<Self> {
|
fn from_lua(value: mlua::Value, lua: &mlua::Lua) -> mlua::Result<Self> {
|
||||||
let uuid = uuid::Uuid::new_v4();
|
let uuid = uuid::Uuid::new_v4();
|
||||||
lua.set_named_registry_value(&uuid.to_string(), value)?;
|
lua.set_named_registry_value(&uuid.to_string(), value)?;
|
||||||
|
@ -33,27 +36,31 @@ impl<T> FromLua for ActionCallback<T> {
|
||||||
uuid,
|
uuid,
|
||||||
lua: lua.clone(),
|
lua: lua.clone(),
|
||||||
}),
|
}),
|
||||||
phantom: PhantomData::<T>,
|
_this: PhantomData::<T>,
|
||||||
|
_state: PhantomData::<S>,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Return proper error here
|
// TODO: Return proper error here
|
||||||
impl<T> ActionCallback<T>
|
impl<T, S> ActionCallback<T, S>
|
||||||
where
|
where
|
||||||
T: IntoLuaMulti + Sync + Send + Clone + 'static,
|
T: IntoLua + Sync + Send + Clone + 'static,
|
||||||
|
S: Serialize,
|
||||||
{
|
{
|
||||||
pub async fn call(&self, state: T) {
|
pub async fn call(&self, this: &T, state: &S) {
|
||||||
let Some(internal) = self.internal.as_ref() else {
|
let Some(internal) = self.internal.as_ref() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let state = internal.lua.to_value(state).unwrap();
|
||||||
|
|
||||||
let callback: mlua::Value = internal
|
let callback: mlua::Value = internal
|
||||||
.lua
|
.lua
|
||||||
.named_registry_value(&internal.uuid.to_string())
|
.named_registry_value(&internal.uuid.to_string())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
match callback {
|
match callback {
|
||||||
mlua::Value::Function(f) => f.call_async::<()>(state).await.unwrap(),
|
mlua::Value::Function(f) => f.call_async::<()>((this.clone(), state)).await.unwrap(),
|
||||||
_ => todo!("Only functions are currently supported"),
|
_ => todo!("Only functions are currently supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ impl mlua::UserData for Timeout {
|
||||||
|
|
||||||
methods.add_async_method(
|
methods.add_async_method(
|
||||||
"start",
|
"start",
|
||||||
|_lua, this, (timeout, callback): (u64, ActionCallback<bool>)| async move {
|
|_lua, this, (timeout, callback): (u64, ActionCallback<mlua::Value, bool>)| async move {
|
||||||
if let Some(handle) = this.state.write().await.handle.take() {
|
if let Some(handle) = this.state.write().await.handle.take() {
|
||||||
handle.abort();
|
handle.abort();
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ impl mlua::UserData for Timeout {
|
||||||
async move {
|
async move {
|
||||||
tokio::time::sleep(timeout).await;
|
tokio::time::sleep(timeout).await;
|
||||||
|
|
||||||
callback.call(false).await;
|
callback.call(&mlua::Nil, &false).await;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
10
config.lua
10
config.lua
|
@ -90,7 +90,7 @@ automation.device_manager:add(IkeaRemote.new({
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
topic = mqtt_z2m("living/remote"),
|
topic = mqtt_z2m("living/remote"),
|
||||||
single_button = true,
|
single_button = true,
|
||||||
callback = function(on)
|
callback = function(_, on)
|
||||||
if on then
|
if on then
|
||||||
if living_mixer:is_on() then
|
if living_mixer:is_on() then
|
||||||
living_mixer:set_on(false)
|
living_mixer:set_on(false)
|
||||||
|
@ -133,7 +133,7 @@ local kettle = IkeaOutlet.new({
|
||||||
})
|
})
|
||||||
automation.device_manager:add(kettle)
|
automation.device_manager:add(kettle)
|
||||||
|
|
||||||
local function set_kettle(on)
|
local function set_kettle(_, on)
|
||||||
kettle:set_on(on)
|
kettle:set_on(on)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ automation.device_manager:add(IkeaRemote.new({
|
||||||
room = "Hallway",
|
room = "Hallway",
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
topic = mqtt_z2m("hallway/remote"),
|
topic = mqtt_z2m("hallway/remote"),
|
||||||
callback = function(on)
|
callback = function(_, on)
|
||||||
hallway_light_automation:switch_callback(on)
|
hallway_light_automation:switch_callback(on)
|
||||||
end,
|
end,
|
||||||
}))
|
}))
|
||||||
|
@ -281,7 +281,7 @@ automation.device_manager:add(ContactSensor.new({
|
||||||
topic = mqtt_automation("presence/contact/frontdoor"),
|
topic = mqtt_automation("presence/contact/frontdoor"),
|
||||||
timeout = debug and 10 or 15 * 60,
|
timeout = debug and 10 or 15 * 60,
|
||||||
},
|
},
|
||||||
callback = function(open)
|
callback = function(_, open)
|
||||||
hallway_light_automation:door_callback(open)
|
hallway_light_automation:door_callback(open)
|
||||||
end,
|
end,
|
||||||
}))
|
}))
|
||||||
|
@ -289,7 +289,7 @@ automation.device_manager:add(ContactSensor.new({
|
||||||
identifier = "hallway_trash",
|
identifier = "hallway_trash",
|
||||||
topic = mqtt_z2m("hallway/trash"),
|
topic = mqtt_z2m("hallway/trash"),
|
||||||
client = mqtt_client,
|
client = mqtt_client,
|
||||||
callback = function(open)
|
callback = function(_, open)
|
||||||
hallway_light_automation:trash_callback(open)
|
hallway_light_automation:trash_callback(open)
|
||||||
end,
|
end,
|
||||||
}))
|
}))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user