LuaDevice macro now uses LuaDeviceCreate trait to create devices from configs
This commit is contained in:
parent
9f636a2572
commit
44a40d4dfa
|
@ -1,30 +1,9 @@
|
|||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{Data, DataStruct, DeriveInput, Fields, FieldsNamed};
|
||||
use syn::DeriveInput;
|
||||
|
||||
pub fn impl_lua_device_macro(ast: &DeriveInput) -> TokenStream {
|
||||
let name = &ast.ident;
|
||||
// TODO: Handle errors properly
|
||||
// This includes making sure one, and only one config is specified
|
||||
let config = if let Data::Struct(DataStruct {
|
||||
fields: Fields::Named(FieldsNamed { ref named, .. }),
|
||||
..
|
||||
}) = ast.data
|
||||
{
|
||||
named
|
||||
.iter()
|
||||
.find(|&field| {
|
||||
field
|
||||
.attrs
|
||||
.iter()
|
||||
.any(|attr| attr.path().is_ident("config"))
|
||||
})
|
||||
.map(|field| field.ty.clone())
|
||||
.unwrap()
|
||||
} else {
|
||||
unimplemented!()
|
||||
};
|
||||
|
||||
let gen = quote! {
|
||||
impl #name {
|
||||
pub fn register_with_lua(lua: &mlua::Lua) -> mlua::Result<()> {
|
||||
|
@ -34,8 +13,10 @@ pub fn impl_lua_device_macro(ast: &DeriveInput) -> TokenStream {
|
|||
impl mlua::UserData for #name {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_async_function("new", |lua, config: mlua::Value| async {
|
||||
let config: #config = mlua::FromLua::from_lua(config, lua)?;
|
||||
let device = #name::create(config).await.map_err(mlua::ExternalError::into_lua_err)?;
|
||||
let config = mlua::FromLua::from_lua(config, lua)?;
|
||||
|
||||
// TODO: Using crate:: could cause issues
|
||||
let device: #name = crate::devices::LuaDeviceCreate::create(config).await.map_err(mlua::ExternalError::into_lua_err)?;
|
||||
|
||||
Ok(crate::device_manager::WrappedDevice::new(Box::new(device)))
|
||||
});
|
||||
|
|
|
@ -8,9 +8,9 @@ use google_home::GoogleHomeDevice;
|
|||
use rumqttc::Publish;
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::config::{InfoConfig, MqttDeviceConfig};
|
||||
use crate::devices::Device;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::OnMqtt;
|
||||
use crate::messages::{AirFilterFanState, AirFilterState, SetAirFilterFanState};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
@ -27,7 +27,6 @@ pub struct AirFilterConfig {
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct AirFilter {
|
||||
#[config]
|
||||
config: AirFilterConfig,
|
||||
|
||||
last_known_state: AirFilterState,
|
||||
|
@ -53,8 +52,12 @@ impl AirFilter {
|
|||
}
|
||||
}
|
||||
|
||||
impl AirFilter {
|
||||
async fn create(config: AirFilterConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for AirFilter {
|
||||
type Config = AirFilterConfig;
|
||||
type Error = rumqttc::ClientError;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = config.info.identifier(), "Setting up AirFilter");
|
||||
|
||||
config
|
||||
|
|
|
@ -3,7 +3,7 @@ use automation_macro::{LuaDevice, LuaDeviceConfig};
|
|||
use google_home::traits::OnOff;
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::Device;
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::device_manager::WrappedDevice;
|
||||
use crate::error::DeviceConfigError;
|
||||
|
@ -26,12 +26,15 @@ pub struct AudioSetupConfig {
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct AudioSetup {
|
||||
#[config]
|
||||
config: AudioSetupConfig,
|
||||
}
|
||||
|
||||
impl AudioSetup {
|
||||
async fn create(config: AudioSetupConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for AudioSetup {
|
||||
type Config = AudioSetupConfig;
|
||||
type Error = DeviceConfigError;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = config.identifier, "Setting up AudioSetup");
|
||||
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@ use mlua::FromLua;
|
|||
use tokio::task::JoinHandle;
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::Device;
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::device_manager::WrappedDevice;
|
||||
use crate::devices::DEFAULT_PRESENCE;
|
||||
|
@ -64,7 +64,6 @@ pub struct ContactSensorConfig {
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct ContactSensor {
|
||||
#[config]
|
||||
config: ContactSensorConfig,
|
||||
|
||||
overall_presence: bool,
|
||||
|
@ -72,8 +71,12 @@ pub struct ContactSensor {
|
|||
handle: Option<JoinHandle<()>>,
|
||||
}
|
||||
|
||||
impl ContactSensor {
|
||||
async fn create(config: ContactSensorConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for ContactSensor {
|
||||
type Config = ContactSensorConfig;
|
||||
type Error = DeviceConfigError;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = config.identifier, "Setting up ContactSensor");
|
||||
|
||||
// Make sure the devices implement the required traits
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use std::convert::Infallible;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use tracing::{trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::devices::Device;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::{OnDarkness, OnPresence};
|
||||
use crate::messages::{DarknessMessage, PresenceMessage};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
@ -20,12 +22,15 @@ pub struct DebugBridgeConfig {
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct DebugBridge {
|
||||
#[config]
|
||||
config: DebugBridgeConfig,
|
||||
}
|
||||
|
||||
impl DebugBridge {
|
||||
async fn create(config: DebugBridgeConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for DebugBridge {
|
||||
type Config = DebugBridgeConfig;
|
||||
type Error = Infallible;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = config.identifier, "Setting up DebugBridge");
|
||||
Ok(Self { config })
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
@ -5,8 +6,8 @@ use automation_macro::{LuaDevice, LuaDeviceConfig};
|
|||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{error, trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::devices::Device;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::{OnDarkness, OnPresence};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -32,7 +33,6 @@ pub struct HueBridgeConfig {
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct HueBridge {
|
||||
#[config]
|
||||
config: HueBridgeConfig,
|
||||
}
|
||||
|
||||
|
@ -41,12 +41,18 @@ struct FlagMessage {
|
|||
flag: bool,
|
||||
}
|
||||
|
||||
impl HueBridge {
|
||||
async fn create(config: HueBridgeConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for HueBridge {
|
||||
type Config = HueBridgeConfig;
|
||||
type Error = Infallible;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Infallible> {
|
||||
trace!(id = config.identifier, "Setting up HueBridge");
|
||||
Ok(Self { config })
|
||||
}
|
||||
}
|
||||
|
||||
impl HueBridge {
|
||||
pub async fn set_flag(&self, flag: Flag, value: bool) {
|
||||
let flag_id = match flag {
|
||||
Flag::Presence => self.config.flags.presence,
|
||||
|
|
|
@ -9,9 +9,8 @@ use google_home::traits::OnOff;
|
|||
use rumqttc::{Publish, SubscribeFilter};
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::Device;
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::OnMqtt;
|
||||
use crate::messages::{RemoteAction, RemoteMessage};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
@ -34,13 +33,16 @@ pub struct HueGroupConfig {
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct HueGroup {
|
||||
#[config]
|
||||
config: HueGroupConfig,
|
||||
}
|
||||
|
||||
// Couple of helper function to get the correct urls
|
||||
impl HueGroup {
|
||||
async fn create(config: HueGroupConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for HueGroup {
|
||||
type Config = HueGroupConfig;
|
||||
type Error = rumqttc::ClientError;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = config.identifier, "Setting up AudioSetup");
|
||||
|
||||
if !config.remotes.is_empty() {
|
||||
|
@ -55,7 +57,9 @@ impl HueGroup {
|
|||
|
||||
Ok(Self { config })
|
||||
}
|
||||
}
|
||||
|
||||
impl HueGroup {
|
||||
fn url_base(&self) -> String {
|
||||
format!("http://{}/api/{}", self.config.addr, self.config.login)
|
||||
}
|
||||
|
|
|
@ -12,9 +12,9 @@ use serde::Deserialize;
|
|||
use tokio::task::JoinHandle;
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::config::{InfoConfig, MqttDeviceConfig};
|
||||
use crate::devices::Device;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::{OnMqtt, OnPresence};
|
||||
use crate::messages::{OnOffMessage, RemoteAction, RemoteMessage};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
@ -47,7 +47,6 @@ pub struct IkeaOutletConfig {
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct IkeaOutlet {
|
||||
#[config]
|
||||
config: IkeaOutletConfig,
|
||||
|
||||
last_known_state: bool,
|
||||
|
@ -71,8 +70,12 @@ async fn set_on(client: WrappedAsyncClient, topic: &str, on: bool) {
|
|||
.ok();
|
||||
}
|
||||
|
||||
impl IkeaOutlet {
|
||||
async fn create(config: IkeaOutletConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for IkeaOutlet {
|
||||
type Config = IkeaOutletConfig;
|
||||
type Error = rumqttc::ClientError;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = config.info.identifier(), "Setting up IkeaOutlet");
|
||||
|
||||
if !config.remotes.is_empty() {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
use std::str::Utf8Error;
|
||||
|
||||
|
@ -12,8 +13,7 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|||
use tokio::net::TcpStream;
|
||||
use tracing::trace;
|
||||
|
||||
use super::Device;
|
||||
use crate::error::DeviceConfigError;
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct KasaOutletConfig {
|
||||
|
@ -24,12 +24,15 @@ pub struct KasaOutletConfig {
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct KasaOutlet {
|
||||
#[config]
|
||||
config: KasaOutletConfig,
|
||||
}
|
||||
|
||||
impl KasaOutlet {
|
||||
async fn create(config: KasaOutletConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for KasaOutlet {
|
||||
type Config = KasaOutletConfig;
|
||||
type Error = Infallible;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = config.identifier, "Setting up KasaOutlet");
|
||||
Ok(Self { config })
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ use automation_macro::{LuaDevice, LuaDeviceConfig};
|
|||
use rumqttc::Publish;
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::devices::Device;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::{self, Event, EventChannel, OnMqtt};
|
||||
use crate::messages::BrightnessMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
@ -27,14 +27,17 @@ pub const DEFAULT: bool = false;
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct LightSensor {
|
||||
#[config]
|
||||
config: LightSensorConfig,
|
||||
|
||||
is_dark: bool,
|
||||
}
|
||||
|
||||
impl LightSensor {
|
||||
async fn create(config: LightSensorConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for LightSensor {
|
||||
type Config = LightSensorConfig;
|
||||
type Error = rumqttc::ClientError;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = config.identifier, "Setting up LightSensor");
|
||||
|
||||
config
|
||||
|
|
|
@ -14,6 +14,7 @@ mod washer;
|
|||
|
||||
use std::fmt::Debug;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_cast::Cast;
|
||||
use google_home::traits::OnOff;
|
||||
use google_home::GoogleHomeDevice;
|
||||
|
@ -34,6 +35,16 @@ pub use self::washer::*;
|
|||
use crate::event::{OnDarkness, OnMqtt, OnNotification, OnPresence};
|
||||
use crate::traits::Timeout;
|
||||
|
||||
#[async_trait]
|
||||
pub trait LuaDeviceCreate {
|
||||
type Config;
|
||||
type Error;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
pub trait Device:
|
||||
Debug
|
||||
+ Sync
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::collections::HashMap;
|
||||
use std::convert::Infallible;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
|
@ -6,8 +7,8 @@ use serde::Serialize;
|
|||
use serde_repr::*;
|
||||
use tracing::{error, trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::devices::Device;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::{self, Event, EventChannel, OnNotification, OnPresence};
|
||||
|
||||
#[derive(Debug, Serialize_repr, Clone, Copy)]
|
||||
|
@ -121,12 +122,15 @@ pub struct NtfyConfig {
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct Ntfy {
|
||||
#[config]
|
||||
config: NtfyConfig,
|
||||
}
|
||||
|
||||
impl Ntfy {
|
||||
async fn create(config: NtfyConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for Ntfy {
|
||||
type Config = NtfyConfig;
|
||||
type Error = Infallible;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = "ntfy", "Setting up Ntfy");
|
||||
Ok(Self { config })
|
||||
}
|
||||
|
|
|
@ -5,9 +5,9 @@ use automation_macro::{LuaDevice, LuaDeviceConfig};
|
|||
use rumqttc::Publish;
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::devices::Device;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::{self, Event, EventChannel, OnMqtt};
|
||||
use crate::messages::PresenceMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
@ -26,14 +26,17 @@ pub const DEFAULT_PRESENCE: bool = false;
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct Presence {
|
||||
#[config]
|
||||
config: PresenceConfig,
|
||||
devices: HashMap<String, bool>,
|
||||
current_overall_presence: bool,
|
||||
}
|
||||
|
||||
impl Presence {
|
||||
async fn create(config: PresenceConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for Presence {
|
||||
type Config = PresenceConfig;
|
||||
type Error = rumqttc::ClientError;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = "ntfy", "Setting up Presence");
|
||||
|
||||
config
|
||||
|
|
|
@ -10,9 +10,8 @@ use google_home::{device, GoogleHomeDevice};
|
|||
use rumqttc::Publish;
|
||||
use tracing::{debug, error, trace};
|
||||
|
||||
use super::Device;
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
use crate::config::{InfoConfig, MqttDeviceConfig};
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::OnMqtt;
|
||||
use crate::messages::ActivateMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
@ -32,12 +31,15 @@ pub struct WakeOnLANConfig {
|
|||
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct WakeOnLAN {
|
||||
#[config]
|
||||
config: WakeOnLANConfig,
|
||||
}
|
||||
|
||||
impl WakeOnLAN {
|
||||
async fn create(config: WakeOnLANConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for WakeOnLAN {
|
||||
type Config = WakeOnLANConfig;
|
||||
type Error = rumqttc::ClientError;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = config.info.identifier(), "Setting up WakeOnLAN");
|
||||
|
||||
config
|
||||
|
|
|
@ -4,9 +4,8 @@ use rumqttc::Publish;
|
|||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::ntfy::Priority;
|
||||
use super::{Device, Notification};
|
||||
use super::{Device, LuaDeviceCreate, Notification};
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::{self, Event, EventChannel, OnMqtt};
|
||||
use crate::messages::PowerMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
@ -27,14 +26,17 @@ pub struct WasherConfig {
|
|||
// TODO: Add google home integration
|
||||
#[derive(Debug, LuaDevice)]
|
||||
pub struct Washer {
|
||||
#[config]
|
||||
config: WasherConfig,
|
||||
|
||||
running: isize,
|
||||
}
|
||||
|
||||
impl Washer {
|
||||
async fn create(config: WasherConfig) -> Result<Self, DeviceConfigError> {
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for Washer {
|
||||
type Config = WasherConfig;
|
||||
type Error = rumqttc::ClientError;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error> {
|
||||
trace!(id = config.identifier, "Setting up Washer");
|
||||
|
||||
config
|
||||
|
|
|
@ -92,13 +92,9 @@ impl MissingWildcard {
|
|||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum DeviceConfigError {
|
||||
#[error("Child '{1}' of device '{0}' does not exist")]
|
||||
MissingChild(String, String),
|
||||
#[error("Device '{0}' does not implement expected trait '{1}'")]
|
||||
MissingTrait(String, String),
|
||||
#[error(transparent)]
|
||||
MissingWildcard(#[from] MissingWildcard),
|
||||
#[error(transparent)]
|
||||
MqttClientError(#[from] rumqttc::ClientError),
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user