Adjusted how we requre Sync + Send, added logger, cleanup dependencies, and added web server using warp and tokio

This commit is contained in:
2022-12-23 04:40:08 +01:00
parent 1b965cd45a
commit 7e3c3223b2
17 changed files with 809 additions and 736 deletions

View File

@@ -1,11 +1,12 @@
use serde::Serialize;
use serde_with::skip_serializing_none;
#[skip_serializing_none]
#[derive(Debug, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Attributes {
#[serde(skip_serializing_if = "Option::is_none")]
pub command_only_on_off: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub query_only_on_off: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scene_reversible: Option<bool>,
}

View File

@@ -1,5 +1,4 @@
use serde::Serialize;
use serde_with::skip_serializing_none;
use crate::{response, types::Type, traits::{AsOnOff, Trait, AsScene}, errors::{DeviceError, ErrorCode}, request::execute::CommandType};
@@ -19,10 +18,9 @@ pub trait GoogleHomeDevice: AsOnOff + AsScene {
fn get_device_info(&self) -> Option<Info> {
None
}
}
// This trait exists just to hide the sync, query and execute function from the user
pub trait Fullfillment: GoogleHomeDevice {
fn sync(&self) -> response::sync::Device {
let name = self.get_device_name();
let mut device = response::sync::Device::new(&self.get_id(), &name.name, self.get_device_type());
@@ -93,8 +91,6 @@ pub trait Fullfillment: GoogleHomeDevice {
}
}
impl<T: GoogleHomeDevice> Fullfillment for T {}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Name {
@@ -119,13 +115,16 @@ impl Name {
}
}
#[skip_serializing_none]
#[derive(Debug, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Info {
#[serde(skip_serializing_if = "Option::is_none")]
pub manufacturer: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub hw_version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sw_version: Option<String>,
// attributes
// customData

View File

@@ -1,6 +1,6 @@
use std::collections::HashMap;
use crate::{request::{Request, Intent, self}, device::Fullfillment, response::{sync, ResponsePayload, query, execute, Response, self, State}, errors::{DeviceError, ErrorCode}};
use crate::{request::{Request, Intent, self}, device::GoogleHomeDevice, response::{sync, ResponsePayload, query, execute, Response, self, State}, errors::{DeviceError, ErrorCode}};
pub struct GoogleHome {
user_id: String,
@@ -12,7 +12,7 @@ impl GoogleHome {
Self { user_id: user_id.into() }
}
pub fn handle_request(&self, request: Request, mut devices: &mut HashMap<String, &mut dyn Fullfillment>) -> Result<Response, anyhow::Error> {
pub fn handle_request(&self, request: Request, mut devices: &mut HashMap<String, &mut dyn GoogleHomeDevice>) -> Result<Response, anyhow::Error> {
// @TODO What do we do if we actually get more then one thing in the input array, right now
// we only respond to the first thing
let payload = request
@@ -30,7 +30,7 @@ impl GoogleHome {
}
}
fn sync(&self, devices: &HashMap<String, &mut dyn Fullfillment>) -> sync::Payload {
fn sync(&self, devices: &HashMap<String, &mut dyn GoogleHomeDevice>) -> sync::Payload {
let mut resp_payload = sync::Payload::new(&self.user_id);
resp_payload.devices = devices
.iter()
@@ -40,7 +40,7 @@ impl GoogleHome {
return resp_payload;
}
fn query(&self, payload: request::query::Payload, devices: &HashMap<String, &mut dyn Fullfillment>) -> query::Payload {
fn query(&self, payload: request::query::Payload, devices: &HashMap<String, &mut dyn GoogleHomeDevice>) -> query::Payload {
let mut resp_payload = query::Payload::new();
resp_payload.devices = payload.devices
.into_iter()
@@ -62,7 +62,7 @@ impl GoogleHome {
}
fn execute(&self, payload: request::execute::Payload, devices: &mut HashMap<String, &mut dyn Fullfillment>) -> execute::Payload {
fn execute(&self, payload: request::execute::Payload, devices: &mut HashMap<String, &mut dyn GoogleHomeDevice>) -> execute::Payload {
let mut resp_payload = response::execute::Payload::new();
payload.commands
@@ -240,7 +240,7 @@ mod tests {
let mut nightstand = TestOutlet::new("bedroom/nightstand");
let mut lamp = TestOutlet::new("living/lamp");
let mut scene = TestScene::new();
let mut devices: HashMap<String, &mut dyn Fullfillment> = HashMap::new();
let mut devices: HashMap<String, &mut dyn GoogleHomeDevice> = HashMap::new();
devices.insert(nightstand.get_id(), &mut nightstand);
devices.insert(lamp.get_id(), &mut lamp);
devices.insert(scene.get_id(), &mut scene);
@@ -280,7 +280,7 @@ mod tests {
let mut nightstand = TestOutlet::new("bedroom/nightstand");
let mut lamp = TestOutlet::new("living/lamp");
let mut scene = TestScene::new();
let mut devices: HashMap<String, &mut dyn Fullfillment> = HashMap::new();
let mut devices: HashMap<String, &mut dyn GoogleHomeDevice> = HashMap::new();
devices.insert(nightstand.get_id(), &mut nightstand);
devices.insert(lamp.get_id(), &mut lamp);
devices.insert(scene.get_id(), &mut scene);
@@ -332,7 +332,7 @@ mod tests {
let mut nightstand = TestOutlet::new("bedroom/nightstand");
let mut lamp = TestOutlet::new("living/lamp");
let mut scene = TestScene::new();
let mut devices: HashMap<String, &mut dyn Fullfillment> = HashMap::new();
let mut devices: HashMap<String, &mut dyn GoogleHomeDevice> = HashMap::new();
devices.insert(nightstand.get_id(), &mut nightstand);
devices.insert(lamp.get_id(), &mut lamp);
devices.insert(scene.get_id(), &mut scene);

View File

@@ -11,5 +11,5 @@ pub mod errors;
mod attributes;
pub use fullfillment::GoogleHome;
pub use device::Fullfillment;
pub use request::Request;
pub use device::GoogleHomeDevice;

View File

@@ -3,7 +3,6 @@ pub mod query;
pub mod execute;
use serde::Serialize;
use serde_with::skip_serializing_none;
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
@@ -26,9 +25,9 @@ pub enum ResponsePayload {
Execute(execute::Payload),
}
#[skip_serializing_none]
#[derive(Debug, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct State {
#[serde(skip_serializing_if = "Option::is_none")]
pub on: Option<bool>,
}

View File

@@ -1,13 +1,13 @@
use serde::Serialize;
use serde_with::skip_serializing_none;
use crate::{response::State, errors::ErrorCode};
#[skip_serializing_none]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Payload {
#[serde(skip_serializing_if = "Option::is_none")]
pub error_code: Option<ErrorCode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub debug_string: Option<String>,
commands: Vec<Command>,
}
@@ -24,14 +24,15 @@ impl Payload {
}
}
#[skip_serializing_none]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Command {
#[serde(skip_serializing_if = "Option::is_none")]
pub error_code: Option<ErrorCode>,
ids: Vec<String>,
status: Status,
#[serde(skip_serializing_if = "Option::is_none")]
pub states: Option<States>,
}

View File

@@ -1,15 +1,15 @@
use std::collections::HashMap;
use serde::Serialize;
use serde_with::skip_serializing_none;
use crate::{response::State, errors::ErrorCode};
#[skip_serializing_none]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Payload {
#[serde(skip_serializing_if = "Option::is_none")]
pub error_code: Option<ErrorCode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub debug_string: Option<String>,
pub devices: HashMap<String, Device>,
}
@@ -33,12 +33,12 @@ pub enum Status {
Error,
}
#[skip_serializing_none]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Device {
online: bool,
status: Status,
#[serde(skip_serializing_if = "Option::is_none")]
error_code: Option<ErrorCode>,
#[serde(flatten)]

View File

@@ -1,5 +1,4 @@
use serde::Serialize;
use serde_with::skip_serializing_none;
use crate::attributes::Attributes;
use crate::device;
@@ -7,12 +6,13 @@ use crate::errors::ErrorCode;
use crate::types::Type;
use crate::traits::Trait;
#[skip_serializing_none]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Payload {
agent_user_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub error_code: Option<ErrorCode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub debug_string: Option<String>,
pub devices: Vec<Device>,
}
@@ -27,7 +27,6 @@ impl Payload {
}
}
#[skip_serializing_none]
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Device {
@@ -37,8 +36,11 @@ pub struct Device {
pub traits: Vec<Trait>,
pub name: device::Name,
pub will_report_state: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub notification_supported_by_agent: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub room_hint: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub device_info: Option<device::Info>,
pub attributes: Attributes,
}