Started working on google home implementation

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

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,
}