feat: WIP
All checks were successful
Build and deploy / build (push) Successful in 10m43s
Build and deploy / Deploy container (push) Has been skipped

This commit is contained in:
2025-09-17 00:17:31 +02:00
parent 580a5187bd
commit 88a1c15f39
11 changed files with 158 additions and 7 deletions

35
Cargo.lock generated
View File

@@ -128,6 +128,7 @@ dependencies = [
"eui48", "eui48",
"google_home", "google_home",
"inventory", "inventory",
"lua_typed",
"mlua", "mlua",
"reqwest", "reqwest",
"rumqttc", "rumqttc",
@@ -345,6 +346,15 @@ dependencies = [
"winnow", "winnow",
] ]
[[package]]
name = "convert_case"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f"
dependencies = [
"unicode-segmentation",
]
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.4" version = "0.9.4"
@@ -1094,6 +1104,25 @@ dependencies = [
"cc", "cc",
] ]
[[package]]
name = "lua_typed"
version = "0.1.0"
source = "git+https://git.huizinga.dev/Dreaded_X/lua_typed#cef241546e679190472b1ea7e5904cf8102f7f4b"
dependencies = [
"lua_typed_macro",
]
[[package]]
name = "lua_typed_macro"
version = "0.1.0"
source = "git+https://git.huizinga.dev/Dreaded_X/lua_typed#cef241546e679190472b1ea7e5904cf8102f7f4b"
dependencies = [
"convert_case",
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]] [[package]]
name = "luajit-src" name = "luajit-src"
version = "210.6.1+f9140a6" version = "210.6.1+f9140a6"
@@ -2256,6 +2285,12 @@ version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "unicode-segmentation"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.9.0" version = "0.9.0"

View File

@@ -37,6 +37,7 @@ indexmap = { version = "2.11.0", features = ["serde"] }
inventory = "0.3.21" inventory = "0.3.21"
itertools = "0.14.0" itertools = "0.14.0"
json_value_merge = "2.0.1" json_value_merge = "2.0.1"
lua_typed = { git = "https://git.huizinga.dev/Dreaded_X/lua_typed" }
mlua = { version = "0.11.3", features = [ mlua = { version = "0.11.3", features = [
"lua54", "lua54",
"vendored", "vendored",

View File

@@ -14,6 +14,7 @@ dyn-clone = { workspace = true }
eui48 = { workspace = true } eui48 = { workspace = true }
google_home = { workspace = true } google_home = { workspace = true }
inventory = { workspace = true } inventory = { workspace = true }
lua_typed = { workspace = true }
mlua = { workspace = true } mlua = { workspace = true }
reqwest = { workspace = true } reqwest = { workspace = true }
rumqttc = { workspace = true } rumqttc = { workspace = true }

View File

@@ -14,6 +14,7 @@ mod zigbee;
use automation_lib::Module; use automation_lib::Module;
use automation_lib::device::{Device, LuaDeviceCreate}; use automation_lib::device::{Device, LuaDeviceCreate};
use lua_typed::Typed;
use tracing::debug; use tracing::debug;
macro_rules! register_device { macro_rules! register_device {
@@ -64,3 +65,12 @@ pub fn create_module(lua: &mlua::Lua) -> mlua::Result<mlua::Table> {
} }
inventory::submit! {Module::new("devices", create_module)} inventory::submit! {Module::new("devices", create_module)}
pub fn generate_definitions() {
println!("{}", ntfy::Priority::generate_full().unwrap());
println!("{}", ntfy::ActionType::generate_full().unwrap());
println!("{}", ntfy::Action::generate_full().unwrap());
println!("{}", ntfy::Notification::generate_full().unwrap());
println!("{}", ntfy::Config::generate_full().unwrap());
println!("{}", ntfy::Ntfy::generate_full().unwrap());
}

View File

@@ -4,12 +4,13 @@ use std::convert::Infallible;
use async_trait::async_trait; use async_trait::async_trait;
use automation_lib::device::{Device, LuaDeviceCreate}; use automation_lib::device::{Device, LuaDeviceCreate};
use automation_macro::{Device, LuaDeviceConfig}; use automation_macro::{Device, LuaDeviceConfig};
use lua_typed::Typed;
use mlua::LuaSerdeExt; use mlua::LuaSerdeExt;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_repr::*; use serde_repr::*;
use tracing::{error, trace, warn}; use tracing::{error, trace, warn};
#[derive(Debug, Serialize_repr, Deserialize, Clone, Copy)] #[derive(Debug, Serialize_repr, Deserialize, Clone, Copy, Typed)]
#[repr(u8)] #[repr(u8)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum Priority { pub enum Priority {
@@ -20,7 +21,7 @@ pub enum Priority {
Max, Max,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone, Typed)]
#[serde(rename_all = "snake_case", tag = "action")] #[serde(rename_all = "snake_case", tag = "action")]
pub enum ActionType { pub enum ActionType {
Broadcast { Broadcast {
@@ -31,7 +32,7 @@ pub enum ActionType {
// Http // Http
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone, Typed)]
pub struct Action { pub struct Action {
#[serde(flatten)] #[serde(flatten)]
pub action: ActionType, pub action: ActionType,
@@ -39,14 +40,14 @@ pub struct Action {
pub clear: Option<bool>, pub clear: Option<bool>,
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize, Typed)]
struct NotificationFinal { struct NotificationFinal {
topic: String, topic: String,
#[serde(flatten)] #[serde(flatten)]
inner: Notification, inner: Notification,
} }
#[derive(Debug, Serialize, Clone, Deserialize)] #[derive(Debug, Serialize, Clone, Deserialize, Typed)]
pub struct Notification { pub struct Notification {
title: String, title: String,
message: Option<String>, message: Option<String>,
@@ -67,7 +68,7 @@ impl Notification {
} }
} }
#[derive(Debug, Clone, LuaDeviceConfig)] #[derive(Debug, Clone, LuaDeviceConfig, Typed)]
pub struct Config { pub struct Config {
#[device_config(default("https://ntfy.sh".into()))] #[device_config(default("https://ntfy.sh".into()))]
pub url: String, pub url: String,
@@ -96,6 +97,21 @@ impl Ntfy {
} }
} }
impl Typed for Ntfy {
fn type_name() -> String {
"Ntfy".into()
}
fn generate_header() -> Option<String> {
Some("---@class Ntfy\n".into())
}
fn generate_members() -> Option<String> {
Some("---@async\n---@param notification Notification\nfunction Ntfy:send_notification(notification) end".into(),
)
}
}
#[async_trait] #[async_trait]
impl LuaDeviceCreate for Ntfy { impl LuaDeviceCreate for Ntfy {
type Config = Config; type Config = Config;

View File

@@ -2,17 +2,21 @@ local devices = require("automation:devices")
local device_manager = require("automation:device_manager") local device_manager = require("automation:device_manager")
local utils = require("automation:utils") local utils = require("automation:utils")
local secrets = require("automation:secrets") local secrets = require("automation:secrets")
local debug = require("automation:variables").debug or false local debug = require("automation:variables").debug and true or false
print(_VERSION) print(_VERSION)
local host = utils.get_hostname() local host = utils.get_hostname()
print("Running @" .. host) print("Running @" .. host)
--- @param topic string
--- @return string
local function mqtt_z2m(topic) local function mqtt_z2m(topic)
return "zigbee2mqtt/" .. topic return "zigbee2mqtt/" .. topic
end end
--- @param topic string
--- @return string
local function mqtt_automation(topic) local function mqtt_automation(topic)
return "automation/" .. topic return "automation/" .. topic
end end

View File

@@ -0,0 +1,42 @@
---@meta
local devices
---@class Action
---@field action
---| "broadcast"
---| "view"
---@field extras table<string, string> | nil
---@field label string | nil
---@field clear boolean|nil
---@alias Priority
---| "min"
---| "low"
---| "default"
---| "high"
---| "max"
---@class Notification
---@field title string
---@field message string | nil
-- NOTE: It might be possible to specify this down to the actual possible values
---@field tags string[] | nil
---@field priority Priority | nil
---@field actions Action[] | nil
---@class Ntfy
local Ntfy
---@async
---@param notification Notification
function Ntfy:send_notification(notification) end
---@class NtfyConfig
---@field topic string
devices.Ntfy = {}
---@param config NtfyConfig
---@return Ntfy
function devices.Ntfy.new(config) end
return devices

View File

@@ -0,0 +1,6 @@
---@meta
---@type table<string, string|nil>
local secrets
return secrets

View File

@@ -0,0 +1,27 @@
---@meta
local utils
---@class Timeout
local Timeout
---@async
---@param timeout number
---@param callback fun()
function Timeout:start(timeout, callback) end
---@async
function Timeout:cancel() end
---@async
---@return boolean
function Timeout:is_waiting() end
utils.Timeout = {}
---@return Timeout
function utils.Timeout.new() end
--- @return string hostname
function utils.get_hostname() end
--- @return number epoch
function utils.get_epoch() end
return utils

View File

@@ -0,0 +1,6 @@
---@meta
---@type table<string, string|nil>
local variables
return variables

View File

@@ -0,0 +1,3 @@
fn main() {
automation_devices::generate_definitions()
}