Initial google home trait macro

This commit is contained in:
2024-07-04 01:39:50 +02:00
parent fb7af4a8b1
commit d84ff8ec8e
5 changed files with 742 additions and 24 deletions

View File

@@ -7,10 +7,12 @@ edition = "2021"
[dependencies]
automation_cast = { path = "../automation_cast/" }
automation_macro = { path = "../automation_macro/" }
serde = { version = "1.0.149", features = ["derive"] }
serde_json = "1.0.89"
thiserror = "1.0.37"
tokio = { version = "1", features = ["sync"] }
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"

View File

@@ -0,0 +1,86 @@
use std::error::Error;
use automation_cast::Cast;
use automation_macro::google_home_traits;
use google_home::errors::ErrorCode;
use google_home::traits::AvailableSpeeds;
trait GoogleHomeDevice: GoogleHomeDeviceFulfillment {}
google_home_traits! {
GoogleHomeDevice,
"action.devices.traits.OnOff" => trait OnOff {
command_only_on_off: Option<bool>,
query_only_on_off: Option<bool>,
async fn on(&self) -> Result<bool, ErrorCode>,
"action.devices.commands.OnOff" => async fn set_on(&self, on: bool) -> Result<(), ErrorCode>,
},
"action.devices.traits.Scene" => trait Scene {
scene_reversible: Option<bool>,
"action.devices.commands.ActivateScene" => async fn set_active(&self, activate: bool) -> Result<(), ErrorCode>,
},
"action.devices.traits.FanSpeed" => trait FanSpeed {
reversible: Option<bool>,
command_only_fan_speed: Option<bool>,
available_fan_speeds: AvailableSpeeds,
fn current_fan_speed_setting(&self) -> Result<String, ErrorCode>,
fn current_fan_speed_percent(&self) -> Result<String, ErrorCode>,
// TODO: Figure out some syntax for optional command?
// Probably better to just force the user to always implement commands?
"action.devices.commands.SetFanSpeed" => fn set_fan_speed(&self, fan_speed: String),
},
"action.devices.traits.HumiditySetting" => trait HumiditySetting {
query_only_humidity_setting: Option<bool>,
fn humidity_ambient_percent(&self) -> Result<Option<isize>, ErrorCode>,
}
}
struct Device {}
impl GoogleHomeDevice for Device {}
#[async_trait::async_trait]
impl OnOff for Device {
fn command_only_on_off(&self) -> Option<bool> {
Some(true)
}
async fn on(&self) -> Result<bool, ErrorCode> {
Ok(true)
}
async fn set_on(&self, _on: bool) -> Result<(), ErrorCode> {
Ok(())
}
}
#[async_trait::async_trait]
impl HumiditySetting for Device {
fn query_only_humidity_setting(&self) -> Option<bool> {
Some(true)
}
fn humidity_ambient_percent(&self) -> Result<Option<isize>, ErrorCode> {
Ok(Some(44))
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let device: Box<dyn GoogleHomeDevice> = Box::new(Device {});
let (traits, sync) = device.sync().await?;
let query = device.query().await?;
println!("{traits:?}");
println!("{sync}");
println!("{query}");
let state = device.execute(Command::OnOff { on: true }).await?;
println!("{state}");
Ok(())
}