Further work on automatically generating lua type definitions
This commit is contained in:
parent
2f494a7dd6
commit
11d5d5db4d
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,2 @@
|
|||
/target
|
||||
.env
|
||||
/definitions/generated
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
mod lua_device;
|
||||
mod lua_device_config;
|
||||
mod lua_type_definition;
|
||||
|
||||
use lua_device::impl_lua_device_macro;
|
||||
use lua_device_config::impl_lua_device_config_macro;
|
||||
use lua_type_definition::impl_lua_type_definition;
|
||||
use syn::{parse_macro_input, DeriveInput};
|
||||
|
||||
#[proc_macro_derive(LuaDevice, attributes(config))]
|
||||
#[proc_macro_derive(LuaDevice)]
|
||||
pub fn lua_device_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let ast = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
|
@ -18,3 +20,10 @@ pub fn lua_device_config_derive(input: proc_macro::TokenStream) -> proc_macro::T
|
|||
|
||||
impl_lua_device_config_macro(&ast).into()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(LuaTypeDefinition, attributes(device_config))]
|
||||
pub fn lua_type_definition_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let ast = parse_macro_input!(input as DeriveInput);
|
||||
|
||||
impl_lua_type_definition(&ast).into()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::DeriveInput;
|
||||
|
@ -12,6 +9,20 @@ pub fn impl_lua_device_macro(ast: &DeriveInput) -> TokenStream {
|
|||
pub fn register_with_lua(lua: &mlua::Lua) -> mlua::Result<()> {
|
||||
lua.globals().set(stringify!(#name), lua.create_proxy::<#name>()?)
|
||||
}
|
||||
|
||||
pub fn generate_lua_definition() -> String {
|
||||
// TODO: Do not hardcode the name of the config type
|
||||
let def = format!(
|
||||
r#"--- @class {0}
|
||||
{0} = {{}}
|
||||
--- @param config {0}Config
|
||||
--- @return WrappedDevice
|
||||
function {0}.new(config) end
|
||||
"#, stringify!(#name)
|
||||
);
|
||||
|
||||
def
|
||||
}
|
||||
}
|
||||
impl mlua::UserData for #name {
|
||||
fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
|
@ -27,19 +38,5 @@ pub fn impl_lua_device_macro(ast: &DeriveInput) -> TokenStream {
|
|||
}
|
||||
};
|
||||
|
||||
let def = format!(
|
||||
r#"--- @meta
|
||||
--- @class {name}
|
||||
{name} = {{}}
|
||||
--- @param config {name}Config
|
||||
--- @return Config
|
||||
function {name}.new(config) end"#
|
||||
);
|
||||
|
||||
File::create(format!("./definitions/generated/{name}.lua"))
|
||||
.unwrap()
|
||||
.write_all(def.as_bytes())
|
||||
.unwrap();
|
||||
|
||||
gen
|
||||
}
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
|
||||
use itertools::Itertools;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, quote_spanned};
|
||||
|
@ -26,7 +23,7 @@ mod kw {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum Argument {
|
||||
pub enum Argument {
|
||||
Flatten {
|
||||
_keyword: kw::flatten,
|
||||
},
|
||||
|
@ -110,8 +107,8 @@ impl Parse for Argument {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Args {
|
||||
args: Punctuated<Argument, Token![,]>,
|
||||
pub(crate) struct Args {
|
||||
pub(crate) args: Punctuated<Argument, Token![,]>,
|
||||
}
|
||||
|
||||
impl Parse for Args {
|
||||
|
@ -221,6 +218,21 @@ fn field_from_lua(field: &Field) -> TokenStream {
|
|||
temp.into()
|
||||
}
|
||||
}),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.as_slice()
|
||||
{
|
||||
[] => value,
|
||||
[value] => value.to_owned(),
|
||||
_ => {
|
||||
return quote_spanned! {field.span() => compile_error!("Field contains duplicate 'from'")}
|
||||
}
|
||||
};
|
||||
|
||||
let value = match args
|
||||
.iter()
|
||||
.filter_map(|arg| match arg {
|
||||
Argument::With { expr, .. } => Some(quote! {
|
||||
{
|
||||
let temp = #value;
|
||||
|
@ -235,7 +247,7 @@ fn field_from_lua(field: &Field) -> TokenStream {
|
|||
[] => value,
|
||||
[value] => value.to_owned(),
|
||||
_ => {
|
||||
return quote_spanned! {field.span() => compile_error!("Only one of either 'from' or 'with' is allowed")}
|
||||
return quote_spanned! {field.span() => compile_error!("Field contains duplicate 'with'")}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -279,15 +291,5 @@ pub fn impl_lua_device_config_macro(ast: &DeriveInput) -> TokenStream {
|
|||
}
|
||||
};
|
||||
|
||||
let mut def = format!("--- @meta\n--- @class {name}\n");
|
||||
for field in fields {
|
||||
def += &format!("--- @field {} any\n", field.ident.clone().unwrap())
|
||||
}
|
||||
|
||||
File::create(format!("./definitions/generated/{name}.lua"))
|
||||
.unwrap()
|
||||
.write_all(def.as_bytes())
|
||||
.unwrap();
|
||||
|
||||
impl_from_lua
|
||||
}
|
||||
|
|
137
automation_macro/src/lua_type_definition.rs
Normal file
137
automation_macro/src/lua_type_definition.rs
Normal file
|
@ -0,0 +1,137 @@
|
|||
use itertools::Itertools;
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, quote_spanned};
|
||||
use syn::spanned::Spanned;
|
||||
use syn::{
|
||||
AngleBracketedGenericArguments, Data, DataStruct, DeriveInput, Field, Fields, FieldsNamed,
|
||||
PathArguments, Type, TypePath,
|
||||
};
|
||||
|
||||
use crate::lua_device_config::{Args, Argument};
|
||||
|
||||
fn field_definition(field: &Field) -> TokenStream {
|
||||
let (args, _): (Vec<_>, Vec<_>) = field
|
||||
.attrs
|
||||
.iter()
|
||||
.filter_map(|attr| {
|
||||
if attr.path().is_ident("device_config") {
|
||||
Some(attr.parse_args::<Args>().map(|args| args.args))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.partition_result();
|
||||
let args: Vec<_> = args.into_iter().flatten().collect();
|
||||
|
||||
let field_name = if let Some(field_name) = args.iter().find_map(|arg| match arg {
|
||||
Argument::Rename { ident, .. } => Some(ident),
|
||||
_ => None,
|
||||
}) {
|
||||
field_name.value()
|
||||
} else {
|
||||
format!("{}", field.ident.clone().unwrap())
|
||||
};
|
||||
|
||||
let mut optional = args
|
||||
.iter()
|
||||
.filter(|arg| matches!(arg, Argument::Default { .. } | Argument::DefaultExpr { .. }))
|
||||
.count()
|
||||
>= 1;
|
||||
|
||||
if args
|
||||
.iter()
|
||||
.filter(|arg| matches!(arg, Argument::Flatten { .. }))
|
||||
.count()
|
||||
>= 1
|
||||
{
|
||||
let field_type = &field.ty;
|
||||
quote! {
|
||||
#field_type::generate_lua_fields().as_str()
|
||||
}
|
||||
} else {
|
||||
let path = if let Some(ty) = args.iter().find_map(|arg| match arg {
|
||||
Argument::From { ty, .. } => Some(ty),
|
||||
_ => None,
|
||||
}) {
|
||||
if let Type::Path(TypePath { path, .. }) = ty {
|
||||
path.clone()
|
||||
} else {
|
||||
todo!();
|
||||
}
|
||||
} else if let Type::Path(TypePath { path, .. }) = field.ty.clone() {
|
||||
path
|
||||
} else {
|
||||
todo!()
|
||||
};
|
||||
|
||||
let seg = path.segments.first().unwrap();
|
||||
let field_type = if seg.ident == "Option" {
|
||||
if let PathArguments::AngleBracketed(AngleBracketedGenericArguments { args, .. }) =
|
||||
seg.arguments.clone()
|
||||
{
|
||||
optional = true;
|
||||
quote! { stringify!(#args) }
|
||||
} else {
|
||||
unreachable!("Option should always have angle brackets");
|
||||
}
|
||||
} else if seg.ident == "Vec" {
|
||||
if let PathArguments::AngleBracketed(AngleBracketedGenericArguments { args, .. }) =
|
||||
seg.arguments.clone()
|
||||
{
|
||||
optional = true;
|
||||
quote! { stringify!(#args[]) }
|
||||
} else {
|
||||
unreachable!("Option should always have angle brackets");
|
||||
}
|
||||
} else {
|
||||
quote! { stringify!(#path).replace(" :: ", "_") }
|
||||
};
|
||||
|
||||
let mut format = "--- @field {} {}".to_string();
|
||||
if optional {
|
||||
format += "|nil";
|
||||
}
|
||||
format += "\n";
|
||||
|
||||
quote! {
|
||||
format!(#format, #field_name, #field_type).as_str()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn impl_lua_type_definition(ast: &DeriveInput) -> TokenStream {
|
||||
let name = &ast.ident;
|
||||
let fields = if let Data::Struct(DataStruct {
|
||||
fields: Fields::Named(FieldsNamed { ref named, .. }),
|
||||
..
|
||||
}) = ast.data
|
||||
{
|
||||
named
|
||||
} else {
|
||||
return quote_spanned! {ast.span() => compile_error!("This macro only works on named structs")};
|
||||
};
|
||||
|
||||
let fields: Vec<_> = fields.iter().map(field_definition).collect();
|
||||
|
||||
let gen = quote! {
|
||||
impl #name {
|
||||
pub fn generate_lua_definition() -> String {
|
||||
let mut def = format!("--- @class {}\n", stringify!(#name));
|
||||
|
||||
def += #name::generate_lua_fields().as_str();
|
||||
|
||||
def
|
||||
}
|
||||
|
||||
pub fn generate_lua_fields() -> String {
|
||||
let mut def = String::new();
|
||||
|
||||
#(def += #fields;)*
|
||||
|
||||
def
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
gen
|
||||
}
|
|
@ -1,27 +1,40 @@
|
|||
--- @meta
|
||||
|
||||
--- @class WrappedDevice
|
||||
WrappedDevice = {}
|
||||
--- @return string
|
||||
function WrappedDevice:get_id() end
|
||||
|
||||
--- @class WrappedAsyncClient
|
||||
|
||||
--- @class EventChannel
|
||||
--- @return EventChannel
|
||||
function automation.device_manager:event_channel() end
|
||||
|
||||
automation = {}
|
||||
|
||||
--- @class Device
|
||||
--- @class Config
|
||||
|
||||
--- @class DeviceManager
|
||||
automation.device_manager = {}
|
||||
--- @param device WrappedDevice
|
||||
function automation.device_manager:add(device) end
|
||||
|
||||
--- @class MqttClient
|
||||
automation.mqtt_client = {}
|
||||
--- @param when string
|
||||
--- @param func function
|
||||
function automation.device_manager:schedule(when, func) end
|
||||
|
||||
--- @param identifier string
|
||||
--- @param config Config
|
||||
--- @return Device
|
||||
function automation.device_manager:create(identifier, config) end
|
||||
automation.util = {}
|
||||
--- @param env string
|
||||
--- @return string
|
||||
function automation.util.get_env(env) end
|
||||
|
||||
--- @class DebugBridge
|
||||
DebugBridge = {}
|
||||
--- @class Fulfillment
|
||||
--- @field openid_url string|nil
|
||||
automation.fulfillment = {}
|
||||
|
||||
--- @class DebugBridgeConfig
|
||||
--- @field topic string
|
||||
--- @class MqttConfig
|
||||
--- @param config MqttConfig
|
||||
--- @return WrappedAsyncClient
|
||||
function automation.new_mqtt_client(config) end
|
||||
|
||||
--- @param config DebugBridgeConfig
|
||||
--- @return Config
|
||||
function DebugBridge.new(config) end
|
||||
--- TODO: Generate this automatically
|
||||
--- @alias OutletType "Outlet"|"Kettle"|"Charger"|"Light"
|
||||
--- @alias TriggerDevicesHelper WrappedDevice[]
|
||||
|
|
183
definitions/generated.lua
Normal file
183
definitions/generated.lua
Normal file
|
@ -0,0 +1,183 @@
|
|||
-- WARN: This file is automatically generated, do not manually edit
|
||||
|
||||
---@meta
|
||||
--- @class MqttDeviceConfig
|
||||
--- @field topic String
|
||||
|
||||
--- @class AirFilter
|
||||
AirFilter = {}
|
||||
--- @param config AirFilterConfig
|
||||
--- @return WrappedDevice
|
||||
function AirFilter.new(config) end
|
||||
|
||||
--- @class AirFilterConfig
|
||||
--- @field name String
|
||||
--- @field room String|nil
|
||||
--- @field topic String
|
||||
--- @field client WrappedAsyncClient
|
||||
|
||||
--- @class AudioSetup
|
||||
AudioSetup = {}
|
||||
--- @param config AudioSetupConfig
|
||||
--- @return WrappedDevice
|
||||
function AudioSetup.new(config) end
|
||||
|
||||
--- @class AudioSetupConfig
|
||||
--- @field identifier String
|
||||
--- @field topic String
|
||||
--- @field mixer WrappedDevice
|
||||
--- @field speakers WrappedDevice
|
||||
--- @field client WrappedAsyncClient
|
||||
|
||||
--- @class ContactSensor
|
||||
ContactSensor = {}
|
||||
--- @param config ContactSensorConfig
|
||||
--- @return WrappedDevice
|
||||
function ContactSensor.new(config) end
|
||||
|
||||
--- @class ContactSensorConfig
|
||||
--- @field identifier String
|
||||
--- @field topic String
|
||||
--- @field presence PresenceDeviceConfig|nil
|
||||
--- @field trigger TriggerConfig|nil
|
||||
--- @field client WrappedAsyncClient
|
||||
|
||||
--- @class PresenceDeviceConfig
|
||||
--- @field topic String
|
||||
--- @field timeout u64
|
||||
|
||||
--- @class TriggerConfig
|
||||
--- @field devices TriggerDevicesHelper
|
||||
--- @field timeout u64|nil
|
||||
|
||||
--- @class DebugBridge
|
||||
DebugBridge = {}
|
||||
--- @param config DebugBridgeConfig
|
||||
--- @return WrappedDevice
|
||||
function DebugBridge.new(config) end
|
||||
|
||||
--- @class DebugBridgeConfig
|
||||
--- @field identifier String
|
||||
--- @field topic String
|
||||
--- @field client WrappedAsyncClient
|
||||
|
||||
--- @class HueBridge
|
||||
HueBridge = {}
|
||||
--- @param config HueBridgeConfig
|
||||
--- @return WrappedDevice
|
||||
function HueBridge.new(config) end
|
||||
|
||||
--- @class HueBridgeConfig
|
||||
--- @field identifier String
|
||||
--- @field ip Ipv4Addr
|
||||
--- @field login String
|
||||
--- @field flags FlagIDs
|
||||
|
||||
--- @class FlagIDs
|
||||
--- @field presence isize
|
||||
--- @field darkness isize
|
||||
|
||||
--- @class HueGroup
|
||||
HueGroup = {}
|
||||
--- @param config HueGroupConfig
|
||||
--- @return WrappedDevice
|
||||
function HueGroup.new(config) end
|
||||
|
||||
--- @class HueGroupConfig
|
||||
--- @field identifier String
|
||||
--- @field ip Ipv4Addr
|
||||
--- @field login String
|
||||
--- @field group_id isize
|
||||
--- @field timer_id isize
|
||||
--- @field scene_id String
|
||||
--- @field remotes MqttDeviceConfig []|nil
|
||||
--- @field client WrappedAsyncClient
|
||||
|
||||
--- @class IkeaOutlet
|
||||
IkeaOutlet = {}
|
||||
--- @param config IkeaOutletConfig
|
||||
--- @return WrappedDevice
|
||||
function IkeaOutlet.new(config) end
|
||||
|
||||
--- @class IkeaOutletConfig
|
||||
--- @field name String
|
||||
--- @field room String|nil
|
||||
--- @field topic String
|
||||
--- @field outlet_type OutletType|nil
|
||||
--- @field timeout u64|nil
|
||||
--- @field remotes MqttDeviceConfig []|nil
|
||||
--- @field client WrappedAsyncClient
|
||||
|
||||
--- @class KasaOutlet
|
||||
KasaOutlet = {}
|
||||
--- @param config KasaOutletConfig
|
||||
--- @return WrappedDevice
|
||||
function KasaOutlet.new(config) end
|
||||
|
||||
--- @class KasaOutletConfig
|
||||
--- @field identifier String
|
||||
--- @field ip Ipv4Addr
|
||||
|
||||
--- @class LightSensor
|
||||
LightSensor = {}
|
||||
--- @param config LightSensorConfig
|
||||
--- @return WrappedDevice
|
||||
function LightSensor.new(config) end
|
||||
|
||||
--- @class LightSensorConfig
|
||||
--- @field identifier String
|
||||
--- @field topic String
|
||||
--- @field min isize
|
||||
--- @field max isize
|
||||
--- @field event_channel EventChannel
|
||||
--- @field client WrappedAsyncClient
|
||||
|
||||
--- @class Ntfy
|
||||
Ntfy = {}
|
||||
--- @param config NtfyConfig
|
||||
--- @return WrappedDevice
|
||||
function Ntfy.new(config) end
|
||||
|
||||
--- @class NtfyConfig
|
||||
--- @field url String|nil
|
||||
--- @field topic String
|
||||
--- @field event_channel EventChannel
|
||||
|
||||
--- @class Presence
|
||||
Presence = {}
|
||||
--- @param config PresenceConfig
|
||||
--- @return WrappedDevice
|
||||
function Presence.new(config) end
|
||||
|
||||
--- @class PresenceConfig
|
||||
--- @field topic String
|
||||
--- @field event_channel EventChannel
|
||||
--- @field client WrappedAsyncClient
|
||||
|
||||
--- @class WakeOnLAN
|
||||
WakeOnLAN = {}
|
||||
--- @param config WakeOnLANConfig
|
||||
--- @return WrappedDevice
|
||||
function WakeOnLAN.new(config) end
|
||||
|
||||
--- @class WakeOnLANConfig
|
||||
--- @field name String
|
||||
--- @field room String|nil
|
||||
--- @field topic String
|
||||
--- @field mac_address MacAddress
|
||||
--- @field broadcast_ip Ipv4Addr|nil
|
||||
--- @field client WrappedAsyncClient
|
||||
|
||||
--- @class Washer
|
||||
Washer = {}
|
||||
--- @param config WasherConfig
|
||||
--- @return WrappedDevice
|
||||
function Washer.new(config) end
|
||||
|
||||
--- @class WasherConfig
|
||||
--- @field identifier String
|
||||
--- @field topic String
|
||||
--- @field threshold f32
|
||||
--- @field event_channel EventChannel
|
||||
--- @field client WrappedAsyncClient
|
||||
|
10
definitions/rust.lua
Normal file
10
definitions/rust.lua
Normal file
|
@ -0,0 +1,10 @@
|
|||
--- @meta
|
||||
|
||||
--- @alias String string
|
||||
|
||||
--- @alias u64 number
|
||||
--- @alias isize number
|
||||
--- @alias f32 number
|
||||
|
||||
--- @alias Ipv4Addr string
|
||||
--- @alias MacAddress string
|
57
src/bin/generate_definitions.rs
Normal file
57
src/bin/generate_definitions.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
use automation::config::MqttDeviceConfig;
|
||||
use automation::devices::{
|
||||
AirFilter, AirFilterConfig, AudioSetup, AudioSetupConfig, ContactSensor, ContactSensorConfig,
|
||||
DebugBridge, DebugBridgeConfig, FlagIDs, HueBridge, HueBridgeConfig, HueGroup, HueGroupConfig,
|
||||
IkeaOutlet, IkeaOutletConfig, KasaOutlet, KasaOutletConfig, LightSensor, LightSensorConfig,
|
||||
Ntfy, NtfyConfig, Presence, PresenceConfig, PresenceDeviceConfig, TriggerConfig, WakeOnLAN,
|
||||
WakeOnLANConfig, Washer, WasherConfig,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
println!("-- WARN: This file is automatically generated, do not manually edit\n");
|
||||
println!("---@meta");
|
||||
|
||||
println!("{}", MqttDeviceConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", AirFilter::generate_lua_definition());
|
||||
println!("{}", AirFilterConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", AudioSetup::generate_lua_definition());
|
||||
println!("{}", AudioSetupConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", ContactSensor::generate_lua_definition());
|
||||
println!("{}", ContactSensorConfig::generate_lua_definition());
|
||||
println!("{}", PresenceDeviceConfig::generate_lua_definition());
|
||||
println!("{}", TriggerConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", DebugBridge::generate_lua_definition());
|
||||
println!("{}", DebugBridgeConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", HueBridge::generate_lua_definition());
|
||||
println!("{}", HueBridgeConfig::generate_lua_definition());
|
||||
println!("{}", FlagIDs::generate_lua_definition());
|
||||
|
||||
println!("{}", HueGroup::generate_lua_definition());
|
||||
println!("{}", HueGroupConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", IkeaOutlet::generate_lua_definition());
|
||||
println!("{}", IkeaOutletConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", KasaOutlet::generate_lua_definition());
|
||||
println!("{}", KasaOutletConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", LightSensor::generate_lua_definition());
|
||||
println!("{}", LightSensorConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", Ntfy::generate_lua_definition());
|
||||
println!("{}", NtfyConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", Presence::generate_lua_definition());
|
||||
println!("{}", PresenceConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", WakeOnLAN::generate_lua_definition());
|
||||
println!("{}", WakeOnLANConfig::generate_lua_definition());
|
||||
|
||||
println!("{}", Washer::generate_lua_definition());
|
||||
println!("{}", WasherConfig::generate_lua_definition());
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
use std::time::Duration;
|
||||
|
||||
use automation_macro::LuaTypeDefinition;
|
||||
use rumqttc::{MqttOptions, Transport};
|
||||
use serde::Deserialize;
|
||||
|
||||
|
@ -52,7 +53,7 @@ fn default_fulfillment_port() -> u16 {
|
|||
7878
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[derive(Debug, Clone, Deserialize, LuaTypeDefinition)]
|
||||
pub struct InfoConfig {
|
||||
pub name: String,
|
||||
pub room: Option<String>,
|
||||
|
@ -68,7 +69,7 @@ impl InfoConfig {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[derive(Debug, Clone, Deserialize, LuaTypeDefinition)]
|
||||
pub struct MqttDeviceConfig {
|
||||
pub topic: String,
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use google_home::device::Name;
|
||||
use google_home::errors::ErrorCode;
|
||||
use google_home::traits::{AvailableSpeeds, FanSpeed, HumiditySetting, OnOff, Speed, SpeedValues};
|
||||
|
@ -15,7 +15,7 @@ use crate::event::OnMqtt;
|
|||
use crate::messages::{AirFilterFanState, AirFilterState, SetAirFilterFanState};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
#[derive(Debug, Clone, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct AirFilterConfig {
|
||||
#[device_config(flatten)]
|
||||
pub info: InfoConfig,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use google_home::traits::OnOff;
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
|
@ -12,7 +12,7 @@ use crate::event::{OnMqtt, OnPresence};
|
|||
use crate::messages::{RemoteAction, RemoteMessage};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
#[derive(Debug, Clone, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct AudioSetupConfig {
|
||||
pub identifier: String,
|
||||
#[device_config(flatten)]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use google_home::traits::OnOff;
|
||||
use mlua::FromLua;
|
||||
use tokio::task::JoinHandle;
|
||||
|
@ -18,11 +18,11 @@ use crate::mqtt::WrappedAsyncClient;
|
|||
use crate::traits::Timeout;
|
||||
|
||||
// NOTE: If we add more presence devices we might need to move this out of here
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
#[derive(Debug, Clone, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct PresenceDeviceConfig {
|
||||
#[device_config(flatten)]
|
||||
pub mqtt: MqttDeviceConfig,
|
||||
#[device_config(with(Duration::from_secs))]
|
||||
#[device_config(from(u64), with(Duration::from_secs))]
|
||||
pub timeout: Duration,
|
||||
}
|
||||
|
||||
|
@ -41,15 +41,15 @@ impl From<TriggerDevicesHelper> for Vec<(WrappedDevice, bool)> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
#[derive(Debug, Clone, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct TriggerConfig {
|
||||
#[device_config(from_lua, from(TriggerDevicesHelper))]
|
||||
pub devices: Vec<(WrappedDevice, bool)>,
|
||||
#[device_config(default, with(|t: Option<_>| t.map(Duration::from_secs)))]
|
||||
#[device_config(default, from(Option<u64>), with(|t: Option<_>| t.map(Duration::from_secs)))]
|
||||
pub timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
#[derive(Debug, Clone, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct ContactSensorConfig {
|
||||
pub identifier: String,
|
||||
#[device_config(flatten)]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::convert::Infallible;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use tracing::{trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
|
@ -11,7 +11,7 @@ use crate::event::{OnDarkness, OnPresence};
|
|||
use crate::messages::{DarknessMessage, PresenceMessage};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, LuaDeviceConfig, Clone)]
|
||||
#[derive(Debug, LuaDeviceConfig, Clone, LuaTypeDefinition)]
|
||||
pub struct DebugBridgeConfig {
|
||||
pub identifier: String,
|
||||
#[device_config(flatten)]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{error, trace, warn};
|
||||
|
||||
|
@ -16,16 +16,16 @@ pub enum Flag {
|
|||
Darkness,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[derive(Debug, Clone, Deserialize, LuaTypeDefinition)]
|
||||
pub struct FlagIDs {
|
||||
presence: isize,
|
||||
darkness: isize,
|
||||
}
|
||||
|
||||
#[derive(Debug, LuaDeviceConfig, Clone)]
|
||||
#[derive(Debug, LuaDeviceConfig, Clone, LuaTypeDefinition)]
|
||||
pub struct HueBridgeConfig {
|
||||
pub identifier: String,
|
||||
#[device_config(rename("ip"), with(|ip| SocketAddr::new(ip, 80)))]
|
||||
#[device_config(rename("ip"), from(Ipv4Addr), with(|ip| SocketAddr::new(ip, 80)))]
|
||||
pub addr: SocketAddr,
|
||||
pub login: String,
|
||||
pub flags: FlagIDs,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use std::net::SocketAddr;
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use google_home::errors::ErrorCode;
|
||||
use google_home::traits::OnOff;
|
||||
use rumqttc::{Publish, SubscribeFilter};
|
||||
|
@ -16,10 +16,10 @@ use crate::messages::{RemoteAction, RemoteMessage};
|
|||
use crate::mqtt::WrappedAsyncClient;
|
||||
use crate::traits::Timeout;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
#[derive(Debug, Clone, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct HueGroupConfig {
|
||||
pub identifier: String,
|
||||
#[device_config(rename("ip"), with(|ip| SocketAddr::new(ip, 80)))]
|
||||
#[device_config(rename("ip"), from(Ipv4Addr), with(|ip| SocketAddr::new(ip, 80)))]
|
||||
pub addr: SocketAddr,
|
||||
pub login: String,
|
||||
pub group_id: isize,
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::time::Duration;
|
|||
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use google_home::errors::ErrorCode;
|
||||
use google_home::traits::{self, OnOff};
|
||||
use google_home::types::Type;
|
||||
|
@ -28,7 +28,7 @@ pub enum OutletType {
|
|||
Light,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
#[derive(Debug, Clone, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct IkeaOutletConfig {
|
||||
#[device_config(flatten)]
|
||||
pub info: InfoConfig,
|
||||
|
@ -36,7 +36,7 @@ pub struct IkeaOutletConfig {
|
|||
pub mqtt: MqttDeviceConfig,
|
||||
#[device_config(default(OutletType::Outlet))]
|
||||
pub outlet_type: OutletType,
|
||||
#[device_config(default, with(|t: Option<_>| t.map(Duration::from_secs)))]
|
||||
#[device_config(default, from(Option<u64>), with(|t: Option<_>| t.map(Duration::from_secs)))]
|
||||
pub timeout: Option<Duration>,
|
||||
#[device_config(default)]
|
||||
pub remotes: Vec<MqttDeviceConfig>,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use std::convert::Infallible;
|
||||
use std::net::SocketAddr;
|
||||
use std::net::{Ipv4Addr, SocketAddr};
|
||||
use std::str::Utf8Error;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use bytes::{Buf, BufMut};
|
||||
use google_home::errors::{self, DeviceError};
|
||||
use google_home::traits;
|
||||
|
@ -15,10 +15,10 @@ use tracing::trace;
|
|||
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
#[derive(Debug, Clone, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct KasaOutletConfig {
|
||||
pub identifier: String,
|
||||
#[device_config(rename("ip"), with(|ip| SocketAddr::new(ip, 9999)))]
|
||||
#[device_config(rename("ip"), from(Ipv4Addr), with(|ip| SocketAddr::new(ip, 9999)))]
|
||||
pub addr: SocketAddr,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use rumqttc::Publish;
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
|
@ -10,14 +10,14 @@ use crate::event::{self, Event, EventChannel, OnMqtt};
|
|||
use crate::messages::BrightnessMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
#[derive(Debug, Clone, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct LightSensorConfig {
|
||||
pub identifier: String,
|
||||
#[device_config(flatten)]
|
||||
pub mqtt: MqttDeviceConfig,
|
||||
pub min: isize,
|
||||
pub max: isize,
|
||||
#[device_config(rename("event_channel"), from_lua, with(|ec: EventChannel| ec.get_tx()))]
|
||||
#[device_config(rename("event_channel"), from(EventChannel), from_lua, with(|ec: EventChannel| ec.get_tx()))]
|
||||
pub tx: event::Sender,
|
||||
#[device_config(from_lua)]
|
||||
pub client: WrappedAsyncClient,
|
||||
|
|
|
@ -7,7 +7,7 @@ mod hue_group;
|
|||
mod ikea_outlet;
|
||||
mod kasa_outlet;
|
||||
mod light_sensor;
|
||||
mod ntfy;
|
||||
pub mod ntfy;
|
||||
mod presence;
|
||||
mod wake_on_lan;
|
||||
mod washer;
|
||||
|
@ -25,7 +25,7 @@ pub use self::hue_group::*;
|
|||
pub use self::ikea_outlet::*;
|
||||
pub use self::kasa_outlet::*;
|
||||
pub use self::light_sensor::*;
|
||||
pub use self::ntfy::{Notification, Ntfy};
|
||||
pub use self::ntfy::{Ntfy, NtfyConfig};
|
||||
pub use self::presence::{Presence, PresenceConfig, DEFAULT_PRESENCE};
|
||||
pub use self::wake_on_lan::*;
|
||||
pub use self::washer::*;
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::collections::HashMap;
|
|||
use std::convert::Infallible;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use serde::Serialize;
|
||||
use serde_repr::*;
|
||||
use tracing::{error, trace, warn};
|
||||
|
@ -111,12 +111,12 @@ impl Default for Notification {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, LuaDeviceConfig)]
|
||||
#[derive(Debug, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct NtfyConfig {
|
||||
#[device_config(default("https://ntfy.sh".into()))]
|
||||
pub url: String,
|
||||
pub topic: String,
|
||||
#[device_config(rename("event_channel"), from_lua, with(|ec: EventChannel| ec.get_tx()))]
|
||||
#[device_config(rename("event_channel"), from_lua, from(EventChannel), with(|ec: EventChannel| ec.get_tx()))]
|
||||
pub tx: event::Sender,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use rumqttc::Publish;
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
|
@ -12,11 +12,11 @@ use crate::event::{self, Event, EventChannel, OnMqtt};
|
|||
use crate::messages::PresenceMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, LuaDeviceConfig)]
|
||||
#[derive(Debug, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct PresenceConfig {
|
||||
#[device_config(flatten)]
|
||||
pub mqtt: MqttDeviceConfig,
|
||||
#[device_config(from_lua, rename("event_channel"), with(|ec: EventChannel| ec.get_tx()))]
|
||||
#[device_config(from_lua, rename("event_channel"), from(EventChannel), with(|ec: EventChannel| ec.get_tx()))]
|
||||
pub tx: event::Sender,
|
||||
#[device_config(from_lua)]
|
||||
pub client: WrappedAsyncClient,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::net::Ipv4Addr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use eui48::MacAddress;
|
||||
use google_home::errors::ErrorCode;
|
||||
use google_home::traits::{self, Scene};
|
||||
|
@ -16,7 +16,7 @@ use crate::event::OnMqtt;
|
|||
use crate::messages::ActivateMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
#[derive(Debug, Clone, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct WakeOnLANConfig {
|
||||
#[device_config(flatten)]
|
||||
pub info: InfoConfig,
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
use async_trait::async_trait;
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig};
|
||||
use automation_macro::{LuaDevice, LuaDeviceConfig, LuaTypeDefinition};
|
||||
use rumqttc::Publish;
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::ntfy::Priority;
|
||||
use super::{Device, LuaDeviceCreate, Notification};
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::devices::ntfy::Notification;
|
||||
use crate::event::{self, Event, EventChannel, OnMqtt};
|
||||
use crate::messages::PowerMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
#[derive(Debug, Clone, LuaDeviceConfig, LuaTypeDefinition)]
|
||||
pub struct WasherConfig {
|
||||
pub identifier: String,
|
||||
#[device_config(flatten)]
|
||||
pub mqtt: MqttDeviceConfig,
|
||||
// Power in Watt
|
||||
pub threshold: f32,
|
||||
#[device_config(rename("event_channel"), from_lua, with(|ec: EventChannel| ec.get_tx()))]
|
||||
#[device_config(rename("event_channel"), from_lua, from(EventChannel), with(|ec: EventChannel| ec.get_tx()))]
|
||||
pub tx: event::Sender,
|
||||
#[device_config(from_lua)]
|
||||
pub client: WrappedAsyncClient,
|
||||
|
|
|
@ -4,7 +4,7 @@ use mlua::FromLua;
|
|||
use rumqttc::Publish;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::devices::Notification;
|
||||
use crate::devices::ntfy::Notification;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Event {
|
||||
|
|
Loading…
Reference in New Issue
Block a user