Started working on google home implementation

This commit is contained in:
Dreaded_X 2022-12-11 23:59:29 +01:00
parent c9bbc35f74
commit 6627174c6f
11 changed files with 346 additions and 0 deletions

20
Cargo.lock generated
View File

@ -13,6 +13,7 @@ name = "automation"
version = "0.1.0"
dependencies = [
"dotenv",
"google-home",
"rumqttc",
"serde",
"serde_json",
@ -191,6 +192,15 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "google-home"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
"uuid",
]
[[package]]
name = "itoa"
version = "1.0.4"
@ -609,6 +619,16 @@ version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "uuid"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c"
dependencies = [
"getrandom",
"serde",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"

View File

@ -10,3 +10,4 @@ rumqttc = "0.18"
serde = { version ="1.0.149", features = ["derive"] }
serde_json = "1.0.89"
dotenv = "0.15.0"
google-home = {path = "./google-home"}

1
google-home/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

129
google-home/Cargo.lock generated Normal file
View File

@ -0,0 +1,129 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "getrandom"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "google-home"
version = "0.1.0"
dependencies = [
"serde",
"serde_json",
"uuid",
]
[[package]]
name = "itoa"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
[[package]]
name = "libc"
version = "0.2.138"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
[[package]]
name = "proc-macro2"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "serde"
version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "syn"
version = "1.0.105"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "unicode-ident"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
[[package]]
name = "uuid"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c"
dependencies = [
"getrandom",
"serde",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"

17
google-home/Cargo.toml Normal file
View File

@ -0,0 +1,17 @@
[package]
name = "google-home"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version ="1.0.149", features = ["derive"] }
serde_json = "1.0.89"
[dependencies.uuid]
version = "1.2.2"
features = [
"v4",
"serde",
]

4
google-home/src/lib.rs Normal file
View File

@ -0,0 +1,4 @@
pub mod request;
pub mod response;
pub mod types;
pub mod traits;

View File

@ -0,0 +1,43 @@
use serde::Deserialize;
use uuid::Uuid;
#[derive(Debug, PartialEq, Eq, Deserialize)]
#[serde(tag = "intent")]
enum Intent {
#[serde(rename = "action.devices.SYNC")]
Sync,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
struct Request {
request_id: Uuid,
inputs: Vec<Intent>,
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use super::*;
#[test]
fn deserialize_sync_request() {
let json = r#"{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"inputs": [
{
"intent": "action.devices.SYNC"
}
]
}"#;
let req: Request = serde_json::from_str(json).unwrap();
assert_eq!(req.request_id, Uuid::from_str("ff36a3cc-ec34-11e6-b1a0-64510650abcf").unwrap());
assert_eq!(req.inputs.len(), 1);
assert_eq!(req.inputs[0], Intent::Sync);
}
}

View File

@ -0,0 +1,44 @@
pub mod sync;
use serde::Serialize;
use uuid::Uuid;
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Response {
request_id: Uuid,
payload: ResponsePayload,
}
#[derive(Debug, Serialize)]
#[serde(untagged)]
pub enum ResponsePayload {
Sync(sync::Payload)
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use crate::{response::sync::Device, types::Type, traits::Trait};
use super::*;
#[test]
fn serialize_sync_response() {
let mut sync_resp = sync::Payload::new("Dreaded_X");
let mut device = Device::new("kitchen/kettle", "Kettle", Type::Kettle);
device.traits.push(Trait::OnOff);
device.room_hint = "Kitchen".into();
sync_resp.add_device(device);
let resp = Response{ request_id: Uuid::from_str("ff36a3cc-ec34-11e6-b1a0-64510650abcf").unwrap(), payload: ResponsePayload::Sync(sync_resp) };
println!("{:?}", resp);
let json = serde_json::to_string(&resp).unwrap();
println!("{}", json);
}
}

View File

@ -0,0 +1,67 @@
use serde::Serialize;
use crate::types::Type;
use crate::traits::Trait;
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Payload {
user_agent_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
error_code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
debug_string: Option<String>,
devices: Vec<Device>,
}
impl Payload {
pub fn new(user_agent_id: &str) -> Self {
Self { user_agent_id: user_agent_id.into(), error_code: None, debug_string: None, devices: Vec::new() }
}
pub fn add_device(&mut self, device: Device) {
self.devices.push(device);
}
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Device {
pub id: String,
#[serde(rename = "type")]
pub device_type: Type,
pub traits: Vec<Trait>,
pub name: DeviceName,
pub will_report_state: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub notification_supported_by_agent: Option<bool>,
#[serde(skip_serializing_if = "String::is_empty")]
pub room_hint: String,
}
impl Device {
pub fn new(id: &str, name: &str, device_type: Type) -> Self {
Self {
id: id.into(),
device_type,
traits: Vec::new(),
name: DeviceName {
default_name: Vec::new(),
name: name.into(),
nicknames: Vec::new() },
will_report_state: true,
notification_supported_by_agent: None,
room_hint: "".into(),
}
}
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DeviceName {
#[serde(skip_serializing_if = "Vec::is_empty")]
pub default_name: Vec<String>,
pub name: String,
#[serde(skip_serializing_if = "Vec::is_empty")]
pub nicknames: Vec<String>,
}

View File

@ -0,0 +1,9 @@
use serde::Serialize;
#[derive(Debug, Serialize)]
pub enum Trait {
#[serde(rename = "action.devices.traits.OnOff")]
OnOff,
#[serde(rename = "action.devices.traits.Scene")]
Scene,
}

11
google-home/src/types.rs Normal file
View File

@ -0,0 +1,11 @@
use serde::Serialize;
#[derive(Debug, Serialize)]
pub enum Type {
#[serde(rename = "action.devices.types.KETTLE")]
Kettle,
#[serde(rename = "action.devices.types.OUTLET")]
Outlet,
#[serde(rename = "action.devices.types.SCENE")]
Scene,
}