diff --git a/rust-toolchain.toml b/rust-toolchain.toml index f22c82b..71b5f26 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2023-11-15" -components = ["rustfmt", "clippy"] +channel = "nightly-2024-07-25" +components = ["rustfmt", "clippy", "rust-analyzer"] profile = "minimal" diff --git a/src/devices/mod.rs b/src/devices/mod.rs index c7a794f..6024dcb 100644 --- a/src/devices/mod.rs +++ b/src/devices/mod.rs @@ -45,6 +45,13 @@ pub trait LuaDeviceCreate { } macro_rules! register_device { + ($lua:expr, $device:ty) => { + $lua.globals() + .set(stringify!($device), $lua.create_proxy::<$device>()?)?; + }; +} + +macro_rules! impl_device { ($lua:expr, $device:ty) => { impl mlua::UserData for $device { fn add_methods<'lua, M: mlua::UserDataMethods<'lua, Self>>(methods: &mut M) { @@ -60,12 +67,23 @@ macro_rules! register_device { }); } } - - $lua.globals() - .set(stringify!($device), $lua.create_proxy::<$device>()?)?; }; } +impl_device!(lua, AirFilter); +impl_device!(lua, AudioSetup); +impl_device!(lua, ContactSensor); +impl_device!(lua, DebugBridge); +impl_device!(lua, HueBridge); +impl_device!(lua, HueGroup); +impl_device!(lua, IkeaOutlet); +impl_device!(lua, KasaOutlet); +impl_device!(lua, LightSensor); +impl_device!(lua, Ntfy); +impl_device!(lua, Presence); +impl_device!(lua, WakeOnLAN); +impl_device!(lua, Washer); + pub fn register_with_lua(lua: &mlua::Lua) -> mlua::Result<()> { register_device!(lua, AirFilter); register_device!(lua, AudioSetup); diff --git a/src/main.rs b/src/main.rs index b88c35c..deec0fa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -#![feature(async_closure)] use std::path::Path; use std::process; @@ -9,13 +8,12 @@ use automation::device_manager::DeviceManager; use automation::error::ApiError; use automation::mqtt::{self, WrappedAsyncClient}; use automation::{devices, LUA}; -use axum::extract::FromRef; +use axum::extract::{FromRef, State}; use axum::http::StatusCode; -use axum::response::IntoResponse; use axum::routing::post; use axum::{Json, Router}; use dotenvy::dotenv; -use google_home::{GoogleHome, Request}; +use google_home::{GoogleHome, Request, Response}; use mlua::LuaSerdeExt; use rumqttc::AsyncClient; use tracing::{debug, error, info, warn}; @@ -23,6 +21,7 @@ use tracing::{debug, error, info, warn}; #[derive(Clone)] struct AppState { pub openid_url: String, + pub device_manager: DeviceManager, } impl FromRef for String { @@ -44,6 +43,24 @@ async fn main() { } } +async fn fulfillment( + State(state): State, + user: User, + Json(payload): Json, +) -> Result, ApiError> { + debug!(username = user.preferred_username, "{payload:#?}"); + let gc = GoogleHome::new(&user.preferred_username); + let devices = state.device_manager.devices().await; + let result = gc + .handle_request(payload, &devices) + .await + .map_err(|err| ApiError::new(StatusCode::INTERNAL_SERVER_ERROR, err.into()))?; + + debug!(username = user.preferred_username, "{result:#?}"); + + Ok(Json(result)) +} + async fn app() -> anyhow::Result<()> { dotenv().ok(); @@ -119,31 +136,14 @@ async fn app() -> anyhow::Result<()> { }; // Create google home fulfillment route - let fulfillment = Router::new().route( - "/google_home", - post(async move |user: User, Json(payload): Json| { - debug!(username = user.preferred_username, "{payload:#?}"); - let gc = GoogleHome::new(&user.preferred_username); - let devices = device_manager.devices().await; - let result = match gc.handle_request(payload, &devices).await { - Ok(result) => result, - Err(err) => { - return ApiError::new(StatusCode::INTERNAL_SERVER_ERROR, err.into()) - .into_response() - } - }; - - debug!(username = user.preferred_username, "{result:#?}"); - - (StatusCode::OK, Json(result)).into_response() - }), - ); + let fulfillment = Router::new().route("/google_home", post(fulfillment)); // Combine together all the routes let app = Router::new() .nest("/fulfillment", fulfillment) .with_state(AppState { openid_url: fulfillment_config.openid_url.clone(), + device_manager, }); // Start the web server