Started working on google home implementation
This commit is contained in:
4
google-home/src/lib.rs
Normal file
4
google-home/src/lib.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
pub mod request;
|
||||
pub mod response;
|
||||
pub mod types;
|
||||
pub mod traits;
|
||||
43
google-home/src/request.rs
Normal file
43
google-home/src/request.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
44
google-home/src/response.rs
Normal file
44
google-home/src/response.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
67
google-home/src/response/sync.rs
Normal file
67
google-home/src/response/sync.rs
Normal 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>,
|
||||
}
|
||||
9
google-home/src/traits.rs
Normal file
9
google-home/src/traits.rs
Normal 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
11
google-home/src/types.rs
Normal 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,
|
||||
}
|
||||
Reference in New Issue
Block a user