Compare commits
No commits in common. "14aabe202d2a647e9ae495011f8f4e5e06d035aa" and "e9f080ef1935f1f4c823c0e9412077f6136dd330" have entirely different histories.
14aabe202d
...
e9f080ef19
4350
Cargo.lock
generated
4350
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
101
Cargo.toml
101
Cargo.toml
|
@ -9,11 +9,45 @@ members = [
|
|||
"automation_cast",
|
||||
"google_home/google_home",
|
||||
"google_home/google_home_macro",
|
||||
"automation_devices",
|
||||
"automation_lib",
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
|
||||
[dependencies]
|
||||
automation_macro = { path = "./automation_macro" }
|
||||
automation_cast = { path = "./automation_cast/" }
|
||||
rumqttc = "0.18"
|
||||
serde = { version = "1.0.149", features = ["derive"] }
|
||||
serde_json = "1.0.89"
|
||||
google_home = { path = "./google_home/google_home/" }
|
||||
paste = "1.0.10"
|
||||
tokio = { version = "1", features = ["rt-multi-thread"] }
|
||||
dotenvy = "0.15.0"
|
||||
reqwest = { version = "0.11.13", features = [
|
||||
"json",
|
||||
"rustls-tls",
|
||||
], default-features = false } # Use rustls, since the other packages also use rustls
|
||||
axum = "0.6.1"
|
||||
serde_repr = "0.1.10"
|
||||
tracing = "0.1.37"
|
||||
bytes = "1.3.0"
|
||||
pollster = "0.2.5"
|
||||
regex = "1.7.0"
|
||||
async-trait = "0.1.61"
|
||||
futures = "0.3.25"
|
||||
eui48 = { version = "1.1.0", default-features = false, features = [
|
||||
"disp_hexstring",
|
||||
"serde",
|
||||
] }
|
||||
thiserror = "1.0.38"
|
||||
anyhow = "1.0.68"
|
||||
wakey = "0.3.0"
|
||||
console-subscriber = "0.1.8"
|
||||
tracing-subscriber = "0.3.16"
|
||||
serde_with = "3.2.0"
|
||||
enum_dispatch = "0.3.12"
|
||||
indexmap = { version = "2.0.0", features = ["serde"] }
|
||||
serde_yaml = "0.9.27"
|
||||
tokio-cron-scheduler = "0.9.4"
|
||||
mlua = { version = "0.10.1", features = [
|
||||
"lua54",
|
||||
"vendored",
|
||||
|
@ -22,67 +56,12 @@ mlua = { version = "0.10.1", features = [
|
|||
"async",
|
||||
"send",
|
||||
] }
|
||||
automation_macro = { path = "./automation_macro" }
|
||||
automation_cast = { path = "./automation_cast" }
|
||||
automation_lib = { path = "./automation_lib" }
|
||||
automation_devices = { path = "./automation_devices" }
|
||||
google_home = { path = "./google_home/google_home" }
|
||||
google_home_macro = { path = "./google_home/google_home_macro" }
|
||||
tokio = { version = "1", features = ["rt-multi-thread"] }
|
||||
rumqttc = "0.24.0"
|
||||
tracing = "0.1.37"
|
||||
anyhow = "1.0.68"
|
||||
async-trait = "0.1.83"
|
||||
axum = "0.7.9"
|
||||
bytes = "1.3.0"
|
||||
dotenvy = "0.15.0"
|
||||
dyn-clone = "1.0.17"
|
||||
eui48 = { version = "1.1.0", features = [
|
||||
"disp_hexstring",
|
||||
"serde",
|
||||
], default-features = false }
|
||||
futures = "0.3.25"
|
||||
hostname = "0.4.0"
|
||||
impls = "1.0.3"
|
||||
indexmap = { version = "2.0.0", features = ["serde"] }
|
||||
itertools = "0.13.0"
|
||||
json_value_merge = "2.0.0"
|
||||
pollster = "0.4.0"
|
||||
proc-macro2 = "1.0.81"
|
||||
quote = "1.0.36"
|
||||
reqwest = { version = "0.12.9", features = [
|
||||
"json",
|
||||
"rustls-tls",
|
||||
], default-features = false } # Use rustls, since the other packages also use rustls
|
||||
serde = { version = "1.0.149", features = ["derive"] }
|
||||
serde_json = "1.0.89"
|
||||
serde_repr = "0.1.10"
|
||||
syn = { version = "2.0.60", features = ["extra-traits", "full"] }
|
||||
thiserror = "2.0.5"
|
||||
tokio-cron-scheduler = "0.13.0"
|
||||
tokio-util = { version = "0.7.11", features = ["full"] }
|
||||
tracing-subscriber = "0.3.16"
|
||||
uuid = "1.8.0"
|
||||
wakey = "0.3.0"
|
||||
zigbee2mqtt-types = { version = "0.4.0", features = ["debug", "philips"] }
|
||||
|
||||
[dependencies]
|
||||
automation_lib = { workspace = true }
|
||||
automation_devices = { workspace = true }
|
||||
google_home = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
hostname = { workspace = true }
|
||||
rumqttc = { workspace = true }
|
||||
axum = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
dotenvy = { workspace = true }
|
||||
tracing-subscriber = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
dyn-clone = "1.0.17"
|
||||
impls = "1.0.3"
|
||||
zigbee2mqtt-types = { version = "0.2.0", features = ["debug", "philips"] }
|
||||
|
||||
[patch.crates-io]
|
||||
wakey = { git = "https://git.huizinga.dev/Dreaded_X/wakey" }
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
[package]
|
||||
name = "automation_devices"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
automation_lib = { workspace = true }
|
||||
automation_macro = { workspace = true }
|
||||
automation_cast = { workspace = true }
|
||||
google_home = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
async-trait = { workspace = true }
|
||||
dyn-clone = { workspace = true }
|
||||
rumqttc = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
impls = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
reqwest = { workspace = true } # Use rustls, since the other packages also use rustls
|
||||
anyhow = { workspace = true }
|
||||
zigbee2mqtt-types = { workspace = true }
|
||||
axum = { workspace = true }
|
||||
bytes = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
eui48 = { workspace = true }
|
||||
wakey = { workspace = true }
|
|
@ -1,28 +0,0 @@
|
|||
[package]
|
||||
name = "automation_lib"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
automation_macro = { workspace = true }
|
||||
automation_cast = { workspace = true }
|
||||
google_home = { workspace = true }
|
||||
rumqttc = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
serde_repr = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
bytes = { workspace = true }
|
||||
pollster = { workspace = true }
|
||||
async-trait = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
tokio-cron-scheduler = { workspace = true }
|
||||
mlua = { workspace = true }
|
||||
tokio-util = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
dyn-clone = { workspace = true }
|
||||
impls = { workspace = true }
|
|
@ -1,99 +0,0 @@
|
|||
use std::fmt::Debug;
|
||||
|
||||
use automation_cast::Cast;
|
||||
use dyn_clone::DynClone;
|
||||
use google_home::traits::OnOff;
|
||||
use mlua::ObjectLike;
|
||||
|
||||
use crate::event::{OnDarkness, OnMqtt, OnNotification, OnPresence};
|
||||
|
||||
// TODO: Make this a proper macro
|
||||
macro_rules! impl_device {
|
||||
($device:ty) => {
|
||||
impl mlua::UserData for $device {
|
||||
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_async_function("new", |_lua, config| async {
|
||||
let device: $device = LuaDeviceCreate::create(config)
|
||||
.await
|
||||
.map_err(mlua::ExternalError::into_lua_err)?;
|
||||
|
||||
Ok(device)
|
||||
});
|
||||
|
||||
methods.add_method("__box", |_lua, this, _: ()| {
|
||||
let b: Box<dyn Device> = Box::new(this.clone());
|
||||
Ok(b)
|
||||
});
|
||||
|
||||
methods.add_async_method("get_id", |_lua, this, _: ()| async move { Ok(this.get_id()) });
|
||||
|
||||
if impls::impls!($device: google_home::traits::OnOff) {
|
||||
methods.add_async_method("set_on", |_lua, this, on: bool| async move {
|
||||
(this.deref().cast() as Option<&dyn google_home::traits::OnOff>)
|
||||
.expect("Cast should be valid")
|
||||
.set_on(on)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
||||
methods.add_async_method("is_on", |_lua, this, _: ()| async move {
|
||||
Ok((this.deref().cast() as Option<&dyn google_home::traits::OnOff>)
|
||||
.expect("Cast should be valid")
|
||||
.on()
|
||||
.await
|
||||
.unwrap())
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) use impl_device;
|
||||
|
||||
#[async_trait::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
|
||||
+ DynClone
|
||||
+ Sync
|
||||
+ Send
|
||||
+ Cast<dyn google_home::Device>
|
||||
+ Cast<dyn OnMqtt>
|
||||
+ Cast<dyn OnPresence>
|
||||
+ Cast<dyn OnDarkness>
|
||||
+ Cast<dyn OnNotification>
|
||||
+ Cast<dyn OnOff>
|
||||
{
|
||||
fn get_id(&self) -> String;
|
||||
}
|
||||
|
||||
impl mlua::FromLua for Box<dyn Device> {
|
||||
fn from_lua(value: mlua::Value, _lua: &mlua::Lua) -> mlua::Result<Self> {
|
||||
match value {
|
||||
mlua::Value::UserData(ud) => {
|
||||
let ud = if ud.is::<Box<dyn Device>>() {
|
||||
ud
|
||||
} else {
|
||||
ud.call_method::<_>("__box", ())?
|
||||
};
|
||||
|
||||
let b = ud.borrow::<Self>()?.clone();
|
||||
Ok(b)
|
||||
}
|
||||
_ => Err(mlua::Error::RuntimeError("Expected user data".into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl mlua::UserData for Box<dyn Device> {}
|
||||
|
||||
dyn_clone::clone_trait_object!(Device);
|
|
@ -7,7 +7,14 @@ edition = "2021"
|
|||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
itertools = { workspace = true }
|
||||
proc-macro2 = { workspace = true }
|
||||
quote = { workspace = true }
|
||||
syn = { workspace = true }
|
||||
automation_cast = { path = "../automation_cast" }
|
||||
async-trait = "0.1.80"
|
||||
itertools = "0.12.1"
|
||||
proc-macro2 = "1.0.81"
|
||||
quote = "1.0.36"
|
||||
serde = { version = "1.0.202", features = ["derive"] }
|
||||
syn = { version = "2.0.60", features = ["extra-traits", "full"] }
|
||||
serde_json = "1.0.118"
|
||||
|
||||
[dev-dependencies]
|
||||
serde = { version = "1.0.202", features = ["derive"] }
|
||||
|
|
|
@ -6,12 +6,13 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
automation_cast = { workspace = true }
|
||||
google_home_macro = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
async-trait = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
json_value_merge = { workspace = true }
|
||||
automation_cast = { path = "../../automation_cast/" }
|
||||
google_home_macro = { path = "../google_home_macro/" }
|
||||
serde = { version = "1.0.149", features = ["derive"] }
|
||||
serde_json = "1.0.89"
|
||||
thiserror = "1.0.37"
|
||||
tokio = { version = "1", features = ["sync", "full"] }
|
||||
async-trait = "0.1.61"
|
||||
futures = "0.3.25"
|
||||
anyhow = "1.0.75"
|
||||
json_value_merge = "2.0.0"
|
||||
|
|
|
@ -7,6 +7,6 @@ edition = "2021"
|
|||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
proc-macro2 = { workspace = true }
|
||||
quote = { workspace = true }
|
||||
syn = { workspace = true }
|
||||
proc-macro2 = "1.0.81"
|
||||
quote = "1.0.36"
|
||||
syn = { version = "2.0.60", features = ["extra-traits", "full"] }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2024-12-06"
|
||||
channel = "nightly-2024-07-25"
|
||||
components = ["rustfmt", "clippy", "rust-analyzer"]
|
||||
profile = "minimal"
|
||||
|
|
|
@ -1,78 +1,10 @@
|
|||
use std::result;
|
||||
|
||||
use axum::async_trait;
|
||||
use axum::extract::{FromRef, FromRequestParts};
|
||||
use axum::http::request::Parts;
|
||||
use axum::http::status::InvalidStatusCode;
|
||||
use axum::http::StatusCode;
|
||||
use axum::response::IntoResponse;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("{source}")]
|
||||
pub struct ApiError {
|
||||
status_code: axum::http::StatusCode,
|
||||
source: Box<dyn std::error::Error>,
|
||||
}
|
||||
|
||||
impl ApiError {
|
||||
pub fn new(status_code: axum::http::StatusCode, source: Box<dyn std::error::Error>) -> Self {
|
||||
Self {
|
||||
status_code,
|
||||
source,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ApiError> for ApiErrorJson {
|
||||
fn from(value: ApiError) -> Self {
|
||||
let error = ApiErrorJsonError {
|
||||
code: value.status_code.as_u16(),
|
||||
status: value.status_code.to_string(),
|
||||
reason: value.source.to_string(),
|
||||
};
|
||||
|
||||
Self { error }
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for ApiError {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
(
|
||||
self.status_code,
|
||||
serde_json::to_string::<ApiErrorJson>(&self.into())
|
||||
.expect("Serialization should not fail"),
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct ApiErrorJsonError {
|
||||
code: u16,
|
||||
status: String,
|
||||
reason: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ApiErrorJson {
|
||||
error: ApiErrorJsonError,
|
||||
}
|
||||
|
||||
impl TryFrom<ApiErrorJson> for ApiError {
|
||||
type Error = InvalidStatusCode;
|
||||
|
||||
fn try_from(value: ApiErrorJson) -> result::Result<Self, Self::Error> {
|
||||
let status_code = axum::http::StatusCode::from_u16(value.error.code)?;
|
||||
let source = value.error.reason.into();
|
||||
|
||||
Ok(Self {
|
||||
status_code,
|
||||
source,
|
||||
})
|
||||
}
|
||||
}
|
||||
use crate::error::{ApiError, ApiErrorJson};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct User {
|
||||
|
@ -93,8 +25,6 @@ where
|
|||
|
||||
// Create a request to the auth server
|
||||
// TODO: Do some discovery to find the correct url for this instead of assuming
|
||||
// TODO: I think we can also just run Authlia in front of the endpoint instead
|
||||
// This would then give us a header containing the logged in user info?
|
||||
let mut req = reqwest::Client::new().get(format!("{}/userinfo", openid_url));
|
||||
|
||||
// Add auth header to the request if it exists
|
|
@ -8,7 +8,7 @@ use tokio::sync::{RwLock, RwLockReadGuard};
|
|||
use tokio_cron_scheduler::{Job, JobScheduler};
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
use crate::device::Device;
|
||||
use crate::devices::Device;
|
||||
use crate::event::{Event, EventChannel, OnDarkness, OnMqtt, OnNotification, OnPresence};
|
||||
|
||||
pub type DeviceMap = HashMap<String, Box<dyn Device>>;
|
|
@ -1,11 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_lib::config::{InfoConfig, MqttDeviceConfig};
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use automation_lib::event::OnMqtt;
|
||||
use automation_lib::messages::{AirFilterFanState, AirFilterState, SetAirFilterFanState};
|
||||
use automation_lib::mqtt::WrappedAsyncClient;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use google_home::device::Name;
|
||||
use google_home::errors::ErrorCode;
|
||||
|
@ -18,6 +13,13 @@ use rumqttc::Publish;
|
|||
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::config::{InfoConfig, MqttDeviceConfig};
|
||||
use crate::devices::Device;
|
||||
use crate::event::OnMqtt;
|
||||
use crate::messages::{AirFilterFanState, AirFilterState, SetAirFilterFanState};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct Config {
|
||||
#[device_config(flatten)]
|
|
@ -2,19 +2,20 @@ use std::sync::Arc;
|
|||
use std::time::Duration;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_lib::action_callback::ActionCallback;
|
||||
use automation_lib::config::MqttDeviceConfig;
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use automation_lib::error::DeviceConfigError;
|
||||
use automation_lib::event::{OnMqtt, OnPresence};
|
||||
use automation_lib::messages::{ContactMessage, PresenceMessage};
|
||||
use automation_lib::mqtt::WrappedAsyncClient;
|
||||
use automation_lib::presence::DEFAULT_PRESENCE;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use tokio::task::JoinHandle;
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
use crate::action_callback::ActionCallback;
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::devices::DEFAULT_PRESENCE;
|
||||
use crate::error::DeviceConfigError;
|
||||
use crate::event::{OnMqtt, OnPresence};
|
||||
use crate::messages::{ContactMessage, PresenceMessage};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
// NOTE: If we add more presence devices we might need to move this out of here
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct PresenceDeviceConfig {
|
|
@ -1,14 +1,16 @@
|
|||
use std::convert::Infallible;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_lib::config::MqttDeviceConfig;
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use automation_lib::event::{OnDarkness, OnPresence};
|
||||
use automation_lib::messages::{DarknessMessage, PresenceMessage};
|
||||
use automation_lib::mqtt::WrappedAsyncClient;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use tracing::{trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::devices::Device;
|
||||
use crate::event::{OnDarkness, OnPresence};
|
||||
use crate::messages::{DarknessMessage, PresenceMessage};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, LuaDeviceConfig, Clone)]
|
||||
pub struct Config {
|
||||
pub identifier: String,
|
|
@ -2,12 +2,14 @@ use std::convert::Infallible;
|
|||
use std::net::SocketAddr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use automation_lib::event::{OnDarkness, OnPresence};
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tracing::{error, trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::devices::Device;
|
||||
use crate::event::{OnDarkness, OnPresence};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Flag {
|
||||
Presence,
|
|
@ -2,13 +2,13 @@ use std::net::SocketAddr;
|
|||
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use automation_lib::mqtt::WrappedAsyncClient;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use google_home::errors::ErrorCode;
|
||||
use google_home::traits::OnOff;
|
||||
use tracing::{error, trace, warn};
|
||||
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct Config {
|
||||
|
@ -120,6 +120,9 @@ impl OnOff for HueGroup {
|
|||
}
|
||||
|
||||
mod message {
|
||||
use std::time::Duration;
|
||||
|
||||
use serde::ser::SerializeStruct;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
@ -161,5 +164,46 @@ mod message {
|
|||
pub fn any_on(&self) -> bool {
|
||||
self.state.any_on
|
||||
}
|
||||
|
||||
// pub fn all_on(&self) -> bool {
|
||||
// self.state.all_on
|
||||
// }
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Timeout {
|
||||
timeout: Option<Duration>,
|
||||
}
|
||||
|
||||
impl Timeout {
|
||||
pub fn new(timeout: Option<Duration>) -> Self {
|
||||
Self { timeout }
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for Timeout {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let len = if self.timeout.is_some() { 2 } else { 1 };
|
||||
let mut state = serializer.serialize_struct("TimerMessage", len)?;
|
||||
if self.timeout.is_some() {
|
||||
state.serialize_field("status", "enabled")?;
|
||||
} else {
|
||||
state.serialize_field("status", "disabled")?;
|
||||
}
|
||||
|
||||
if let Some(timeout) = self.timeout {
|
||||
let seconds = timeout.as_secs() % 60;
|
||||
let minutes = (timeout.as_secs() / 60) % 60;
|
||||
let hours = timeout.as_secs() / 3600;
|
||||
|
||||
let time = format!("PT{hours:<02}:{minutes:<02}:{seconds:<02}");
|
||||
state.serialize_field("localtime", &time)?;
|
||||
};
|
||||
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,15 @@
|
|||
use async_trait::async_trait;
|
||||
use automation_lib::action_callback::ActionCallback;
|
||||
use automation_lib::config::{InfoConfig, MqttDeviceConfig};
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use automation_lib::event::OnMqtt;
|
||||
use automation_lib::mqtt::WrappedAsyncClient;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use axum::async_trait;
|
||||
use rumqttc::{matches, Publish};
|
||||
use tracing::{debug, trace, warn};
|
||||
use zigbee2mqtt_types::philips::{Zigbee929003017102, Zigbee929003017102Action};
|
||||
use zigbee2mqtt_types::vendors::philips::Zigbee929003017102;
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::action_callback::ActionCallback;
|
||||
use crate::config::{InfoConfig, MqttDeviceConfig};
|
||||
use crate::devices::Device;
|
||||
use crate::event::OnMqtt;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct Config {
|
||||
|
@ -70,8 +72,12 @@ impl OnMqtt for HueSwitch {
|
|||
debug!(id = Device::get_id(self), "Remote action = {:?}", action);
|
||||
|
||||
match action {
|
||||
Zigbee929003017102Action::LeftPress => self.config.left_callback.call(()).await,
|
||||
Zigbee929003017102Action::RightPress => self.config.right_callback.call(()).await,
|
||||
zigbee2mqtt_types::vendors::philips::Zigbee929003017102Action::Leftpress => {
|
||||
self.config.left_callback.call(()).await
|
||||
}
|
||||
zigbee2mqtt_types::vendors::philips::Zigbee929003017102Action::Rightpress => {
|
||||
self.config.right_callback.call(()).await
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
|
@ -2,12 +2,6 @@ use std::sync::Arc;
|
|||
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use automation_lib::action_callback::ActionCallback;
|
||||
use automation_lib::config::{InfoConfig, MqttDeviceConfig};
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use automation_lib::event::{OnMqtt, OnPresence};
|
||||
use automation_lib::messages::OnOffMessage;
|
||||
use automation_lib::mqtt::WrappedAsyncClient;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use google_home::device;
|
||||
use google_home::errors::ErrorCode;
|
||||
|
@ -18,6 +12,14 @@ use serde::Deserialize;
|
|||
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::action_callback::ActionCallback;
|
||||
use crate::config::{InfoConfig, MqttDeviceConfig};
|
||||
use crate::devices::Device;
|
||||
use crate::event::{OnMqtt, OnPresence};
|
||||
use crate::messages::OnOffMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq, Eq, Copy)]
|
||||
pub enum OutletType {
|
||||
Outlet,
|
|
@ -1,14 +1,16 @@
|
|||
use automation_lib::action_callback::ActionCallback;
|
||||
use automation_lib::config::{InfoConfig, MqttDeviceConfig};
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use automation_lib::event::OnMqtt;
|
||||
use automation_lib::messages::{RemoteAction, RemoteMessage};
|
||||
use automation_lib::mqtt::WrappedAsyncClient;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use axum::async_trait;
|
||||
use rumqttc::{matches, Publish};
|
||||
use tracing::{debug, error, trace};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::action_callback::ActionCallback;
|
||||
use crate::config::{InfoConfig, MqttDeviceConfig};
|
||||
use crate::devices::Device;
|
||||
use crate::event::OnMqtt;
|
||||
use crate::messages::RemoteMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct Config {
|
||||
#[device_config(flatten)]
|
||||
|
@ -71,14 +73,14 @@ impl OnMqtt for IkeaRemote {
|
|||
|
||||
let on = if self.config.single_button {
|
||||
match action {
|
||||
RemoteAction::On => Some(true),
|
||||
RemoteAction::BrightnessMoveUp => Some(false),
|
||||
crate::messages::RemoteAction::On => Some(true),
|
||||
crate::messages::RemoteAction::BrightnessMoveUp => Some(false),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
match action {
|
||||
RemoteAction::On => Some(true),
|
||||
RemoteAction::Off => Some(false),
|
||||
crate::messages::RemoteAction::On => Some(true),
|
||||
crate::messages::RemoteAction::Off => Some(false),
|
||||
_ => None,
|
||||
}
|
||||
};
|
|
@ -3,8 +3,6 @@ use std::net::SocketAddr;
|
|||
use std::str::Utf8Error;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use automation_lib::event::OnPresence;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use bytes::{Buf, BufMut};
|
||||
use google_home::errors::{self, DeviceError};
|
||||
|
@ -15,6 +13,9 @@ use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|||
use tokio::net::TcpStream;
|
||||
use tracing::{debug, trace};
|
||||
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
use crate::event::OnPresence;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct Config {
|
||||
pub identifier: String,
|
|
@ -1,16 +1,18 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_lib::config::MqttDeviceConfig;
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use automation_lib::event::{self, Event, EventChannel, OnMqtt};
|
||||
use automation_lib::messages::BrightnessMessage;
|
||||
use automation_lib::mqtt::WrappedAsyncClient;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use rumqttc::Publish;
|
||||
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::devices::Device;
|
||||
use crate::event::{self, Event, EventChannel, OnMqtt};
|
||||
use crate::messages::BrightnessMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct Config {
|
||||
pub identifier: String,
|
|
@ -8,13 +8,19 @@ mod ikea_outlet;
|
|||
mod ikea_remote;
|
||||
mod kasa_outlet;
|
||||
mod light_sensor;
|
||||
mod ntfy;
|
||||
mod presence;
|
||||
mod wake_on_lan;
|
||||
mod washer;
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::ops::Deref;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_cast::Cast;
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use dyn_clone::DynClone;
|
||||
use google_home::traits::OnOff;
|
||||
use mlua::ObjectLike;
|
||||
|
||||
pub use self::air_filter::AirFilter;
|
||||
pub use self::contact_sensor::ContactSensor;
|
||||
|
@ -26,8 +32,21 @@ pub use self::ikea_outlet::IkeaOutlet;
|
|||
pub use self::ikea_remote::IkeaRemote;
|
||||
pub use self::kasa_outlet::KasaOutlet;
|
||||
pub use self::light_sensor::LightSensor;
|
||||
pub use self::ntfy::{Notification, Ntfy};
|
||||
pub use self::presence::{Presence, DEFAULT_PRESENCE};
|
||||
pub use self::wake_on_lan::WakeOnLAN;
|
||||
pub use self::washer::Washer;
|
||||
use crate::event::{OnDarkness, OnMqtt, OnNotification, OnPresence};
|
||||
|
||||
#[async_trait]
|
||||
pub trait LuaDeviceCreate {
|
||||
type Config;
|
||||
type Error;
|
||||
|
||||
async fn create(config: Self::Config) -> Result<Self, Self::Error>
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
macro_rules! register_device {
|
||||
($lua:expr, $device:ty) => {
|
||||
|
@ -41,7 +60,7 @@ macro_rules! impl_device {
|
|||
impl mlua::UserData for $device {
|
||||
fn add_methods<M: mlua::UserDataMethods<Self>>(methods: &mut M) {
|
||||
methods.add_async_function("new", |_lua, config| async {
|
||||
let device: $device = LuaDeviceCreate::create(config)
|
||||
let device: $device = crate::devices::LuaDeviceCreate::create(config)
|
||||
.await
|
||||
.map_err(mlua::ExternalError::into_lua_err)?;
|
||||
|
||||
|
@ -55,9 +74,9 @@ macro_rules! impl_device {
|
|||
|
||||
methods.add_async_method("get_id", |_lua, this, _: ()| async move { Ok(this.get_id()) });
|
||||
|
||||
if impls::impls!($device: google_home::traits::OnOff) {
|
||||
if impls::impls!($device: OnOff) {
|
||||
methods.add_async_method("set_on", |_lua, this, on: bool| async move {
|
||||
(this.deref().cast() as Option<&dyn google_home::traits::OnOff>)
|
||||
(this.deref().cast() as Option<&dyn OnOff>)
|
||||
.expect("Cast should be valid")
|
||||
.set_on(on)
|
||||
.await
|
||||
|
@ -67,7 +86,7 @@ macro_rules! impl_device {
|
|||
});
|
||||
|
||||
methods.add_async_method("is_on", |_lua, this, _: ()| async move {
|
||||
Ok((this.deref().cast() as Option<&dyn google_home::traits::OnOff>)
|
||||
Ok((this.deref().cast() as Option<&dyn OnOff>)
|
||||
.expect("Cast should be valid")
|
||||
.on()
|
||||
.await
|
||||
|
@ -89,6 +108,8 @@ impl_device!(IkeaOutlet);
|
|||
impl_device!(IkeaRemote);
|
||||
impl_device!(KasaOutlet);
|
||||
impl_device!(LightSensor);
|
||||
impl_device!(Ntfy);
|
||||
impl_device!(Presence);
|
||||
impl_device!(WakeOnLAN);
|
||||
impl_device!(Washer);
|
||||
|
||||
|
@ -103,8 +124,47 @@ pub fn register_with_lua(lua: &mlua::Lua) -> mlua::Result<()> {
|
|||
register_device!(lua, IkeaRemote);
|
||||
register_device!(lua, KasaOutlet);
|
||||
register_device!(lua, LightSensor);
|
||||
register_device!(lua, Ntfy);
|
||||
register_device!(lua, Presence);
|
||||
register_device!(lua, WakeOnLAN);
|
||||
register_device!(lua, Washer);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub trait Device:
|
||||
Debug
|
||||
+ DynClone
|
||||
+ Sync
|
||||
+ Send
|
||||
+ Cast<dyn google_home::Device>
|
||||
+ Cast<dyn OnMqtt>
|
||||
+ Cast<dyn OnMqtt>
|
||||
+ Cast<dyn OnPresence>
|
||||
+ Cast<dyn OnDarkness>
|
||||
+ Cast<dyn OnNotification>
|
||||
+ Cast<dyn OnOff>
|
||||
{
|
||||
fn get_id(&self) -> String;
|
||||
}
|
||||
|
||||
impl mlua::FromLua for Box<dyn Device> {
|
||||
fn from_lua(value: mlua::Value, _lua: &mlua::Lua) -> mlua::Result<Self> {
|
||||
match value {
|
||||
mlua::Value::UserData(ud) => {
|
||||
let ud = if ud.is::<Box<dyn Device>>() {
|
||||
ud
|
||||
} else {
|
||||
ud.call_method::<_>("__box", ())?
|
||||
};
|
||||
|
||||
let b = ud.borrow::<Self>()?.clone();
|
||||
Ok(b)
|
||||
}
|
||||
_ => Err(mlua::Error::RuntimeError("Expected user data".into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl mlua::UserData for Box<dyn Device> {}
|
||||
|
||||
dyn_clone::clone_trait_object!(Device);
|
|
@ -1,15 +1,14 @@
|
|||
use std::collections::HashMap;
|
||||
use std::convert::Infallible;
|
||||
use std::ops::Deref;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_cast::Cast;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use serde::Serialize;
|
||||
use serde_repr::*;
|
||||
use tracing::{error, trace, warn};
|
||||
|
||||
use crate::device::{impl_device, Device, LuaDeviceCreate};
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::devices::Device;
|
||||
use crate::event::{self, Event, EventChannel, OnNotification, OnPresence};
|
||||
|
||||
#[derive(Debug, Serialize_repr, Clone, Copy)]
|
||||
|
@ -126,8 +125,6 @@ pub struct Ntfy {
|
|||
config: Config,
|
||||
}
|
||||
|
||||
impl_device!(Ntfy);
|
||||
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for Ntfy {
|
||||
type Config = Config;
|
|
@ -1,16 +1,15 @@
|
|||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_cast::Cast;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use rumqttc::Publish;
|
||||
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
use super::LuaDeviceCreate;
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::device::{impl_device, Device, LuaDeviceCreate};
|
||||
use crate::devices::Device;
|
||||
use crate::event::{self, Event, EventChannel, OnMqtt};
|
||||
use crate::messages::PresenceMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
@ -49,8 +48,6 @@ impl Presence {
|
|||
}
|
||||
}
|
||||
|
||||
impl_device!(Presence);
|
||||
|
||||
#[async_trait]
|
||||
impl LuaDeviceCreate for Presence {
|
||||
type Config = Config;
|
|
@ -1,11 +1,6 @@
|
|||
use std::net::Ipv4Addr;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_lib::config::{InfoConfig, MqttDeviceConfig};
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use automation_lib::event::OnMqtt;
|
||||
use automation_lib::messages::ActivateMessage;
|
||||
use automation_lib::mqtt::WrappedAsyncClient;
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use eui48::MacAddress;
|
||||
use google_home::device;
|
||||
|
@ -15,6 +10,12 @@ use google_home::types::Type;
|
|||
use rumqttc::Publish;
|
||||
use tracing::{debug, error, trace};
|
||||
|
||||
use super::{Device, LuaDeviceCreate};
|
||||
use crate::config::{InfoConfig, MqttDeviceConfig};
|
||||
use crate::event::OnMqtt;
|
||||
use crate::messages::ActivateMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct Config {
|
||||
#[device_config(flatten)]
|
|
@ -1,17 +1,18 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use automation_lib::config::MqttDeviceConfig;
|
||||
use automation_lib::device::{Device, LuaDeviceCreate};
|
||||
use automation_lib::event::{self, Event, EventChannel, OnMqtt};
|
||||
use automation_lib::messages::PowerMessage;
|
||||
use automation_lib::mqtt::WrappedAsyncClient;
|
||||
use automation_lib::ntfy::{Notification, Priority};
|
||||
use automation_macro::LuaDeviceConfig;
|
||||
use rumqttc::Publish;
|
||||
use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
use tracing::{debug, error, trace, warn};
|
||||
|
||||
use super::ntfy::Priority;
|
||||
use super::{Device, LuaDeviceCreate, Notification};
|
||||
use crate::config::MqttDeviceConfig;
|
||||
use crate::event::{self, Event, EventChannel, OnMqtt};
|
||||
use crate::messages::PowerMessage;
|
||||
use crate::mqtt::WrappedAsyncClient;
|
||||
|
||||
#[derive(Debug, Clone, LuaDeviceConfig)]
|
||||
pub struct Config {
|
||||
pub identifier: String,
|
|
@ -1,7 +1,10 @@
|
|||
use std::{error, fmt, result};
|
||||
|
||||
use axum::http::status::InvalidStatusCode;
|
||||
use axum::response::IntoResponse;
|
||||
use bytes::Bytes;
|
||||
use rumqttc::ClientError;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -98,3 +101,68 @@ pub enum LightSensorError {
|
|||
#[error(transparent)]
|
||||
SubscribeError(#[from] ClientError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
#[error("{source}")]
|
||||
pub struct ApiError {
|
||||
status_code: axum::http::StatusCode,
|
||||
source: Box<dyn std::error::Error>,
|
||||
}
|
||||
|
||||
impl ApiError {
|
||||
pub fn new(status_code: axum::http::StatusCode, source: Box<dyn std::error::Error>) -> Self {
|
||||
Self {
|
||||
status_code,
|
||||
source,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ApiError> for ApiErrorJson {
|
||||
fn from(value: ApiError) -> Self {
|
||||
let error = ApiErrorJsonError {
|
||||
code: value.status_code.as_u16(),
|
||||
status: value.status_code.to_string(),
|
||||
reason: value.source.to_string(),
|
||||
};
|
||||
|
||||
Self { error }
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for ApiError {
|
||||
fn into_response(self) -> axum::response::Response {
|
||||
(
|
||||
self.status_code,
|
||||
serde_json::to_string::<ApiErrorJson>(&self.into())
|
||||
.expect("Serialization should not fail"),
|
||||
)
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct ApiErrorJsonError {
|
||||
code: u16,
|
||||
status: String,
|
||||
reason: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ApiErrorJson {
|
||||
error: ApiErrorJsonError,
|
||||
}
|
||||
|
||||
impl TryFrom<ApiErrorJson> for ApiError {
|
||||
type Error = InvalidStatusCode;
|
||||
|
||||
fn try_from(value: ApiErrorJson) -> result::Result<Self, Self::Error> {
|
||||
let status_code = axum::http::StatusCode::from_u16(value.error.code)?;
|
||||
let source = value.error.reason.into();
|
||||
|
||||
Ok(Self {
|
||||
status_code,
|
||||
source,
|
||||
})
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ use mlua::FromLua;
|
|||
use rumqttc::Publish;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::ntfy::Notification;
|
||||
use crate::devices::Notification;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Event {
|
|
@ -3,14 +3,13 @@
|
|||
#![feature(let_chains)]
|
||||
|
||||
pub mod action_callback;
|
||||
pub mod auth;
|
||||
pub mod config;
|
||||
pub mod device;
|
||||
pub mod device_manager;
|
||||
pub mod devices;
|
||||
pub mod error;
|
||||
pub mod event;
|
||||
pub mod helpers;
|
||||
pub mod messages;
|
||||
pub mod mqtt;
|
||||
pub mod ntfy;
|
||||
pub mod presence;
|
||||
pub mod schedule;
|
29
src/main.rs
29
src/main.rs
|
@ -1,16 +1,13 @@
|
|||
mod web;
|
||||
|
||||
use std::net::SocketAddr;
|
||||
use std::path::Path;
|
||||
use std::process;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use automation_lib::config::{FulfillmentConfig, MqttConfig};
|
||||
use automation_lib::device_manager::DeviceManager;
|
||||
use automation_lib::helpers;
|
||||
use automation_lib::mqtt::{self, WrappedAsyncClient};
|
||||
use automation_lib::ntfy::Ntfy;
|
||||
use automation_lib::presence::Presence;
|
||||
use automation::auth::User;
|
||||
use automation::config::{FulfillmentConfig, MqttConfig};
|
||||
use automation::device_manager::DeviceManager;
|
||||
use automation::error::ApiError;
|
||||
use automation::mqtt::{self, WrappedAsyncClient};
|
||||
use automation::{devices, helpers};
|
||||
use axum::extract::{FromRef, State};
|
||||
use axum::http::StatusCode;
|
||||
use axum::routing::post;
|
||||
|
@ -19,9 +16,7 @@ use dotenvy::dotenv;
|
|||
use google_home::{GoogleHome, Request, Response};
|
||||
use mlua::LuaSerdeExt;
|
||||
use rumqttc::AsyncClient;
|
||||
use tokio::net::TcpListener;
|
||||
use tracing::{debug, error, info, warn};
|
||||
use web::{ApiError, User};
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AppState {
|
||||
|
@ -116,11 +111,8 @@ async fn app() -> anyhow::Result<()> {
|
|||
|
||||
lua.globals().set("automation", automation)?;
|
||||
|
||||
automation_devices::register_with_lua(&lua)?;
|
||||
devices::register_with_lua(&lua)?;
|
||||
helpers::register_with_lua(&lua)?;
|
||||
lua.globals().set("Ntfy", lua.create_proxy::<Ntfy>()?)?;
|
||||
lua.globals()
|
||||
.set("Presence", lua.create_proxy::<Presence>()?)?;
|
||||
|
||||
// TODO: Make this not hardcoded
|
||||
let config_filename = std::env::var("AUTOMATION_CONFIG").unwrap_or("./config.lua".into());
|
||||
|
@ -156,10 +148,11 @@ async fn app() -> anyhow::Result<()> {
|
|||
});
|
||||
|
||||
// Start the web server
|
||||
let addr: SocketAddr = fulfillment_config.into();
|
||||
let addr = fulfillment_config.into();
|
||||
info!("Server started on http://{addr}");
|
||||
let listener = TcpListener::bind(addr).await?;
|
||||
axum::serve(listener, app).await?;
|
||||
axum::Server::try_bind(&addr)?
|
||||
.serve(app.into_make_service())
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user