Added Air Filter support
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2023-10-07 05:34:33 +02:00
parent 7ee40f6bb8
commit b12b76bd50
13 changed files with 347 additions and 11 deletions

View File

@@ -1,5 +1,7 @@
use serde::Serialize;
use crate::traits::AvailableSpeeds;
#[derive(Debug, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Attributes {
@@ -9,4 +11,10 @@ pub struct Attributes {
pub query_only_on_off: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scene_reversible: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reversible: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub command_only_fan_speed: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub available_fan_speeds: Option<AvailableSpeeds>,
}

View File

@@ -5,7 +5,7 @@ use crate::{
errors::{DeviceError, ErrorCode},
request::execute::CommandType,
response,
traits::{OnOff, Scene, Trait},
traits::{FanSpeed, OnOff, Scene, Trait},
types::Type,
};
@@ -44,7 +44,7 @@ where
}
#[async_trait]
#[impl_cast::device(As: OnOff + Scene)]
#[impl_cast::device(As: OnOff + Scene + FanSpeed)]
pub trait GoogleHomeDevice: AsGoogleHomeDevice + Sync + Send + 'static {
fn get_device_type(&self) -> Type;
fn get_device_name(&self) -> Name;
@@ -90,6 +90,13 @@ pub trait GoogleHomeDevice: AsGoogleHomeDevice + Sync + Send + 'static {
device.attributes.scene_reversible = scene.is_scene_reversible();
}
// FanSpeed
if let Some(fan_speed) = As::<dyn FanSpeed>::cast(self) {
traits.push(Trait::FanSpeed);
device.attributes.command_only_fan_speed = fan_speed.command_only_fan_speed();
device.attributes.available_fan_speeds = Some(fan_speed.available_speeds());
}
device.traits = traits;
device
@@ -110,25 +117,35 @@ pub trait GoogleHomeDevice: AsGoogleHomeDevice + Sync + Send + 'static {
.ok();
}
// FanSpeed
if let Some(fan_speed) = As::<dyn FanSpeed>::cast(self) {
device.state.current_fan_speed_setting = Some(fan_speed.current_speed().await);
}
device
}
async fn execute(&mut self, command: &CommandType) -> Result<(), ErrorCode> {
match command {
CommandType::OnOff { on } => {
if let Some(on_off) = As::<dyn OnOff>::cast_mut(self) {
on_off.set_on(*on).await?;
if let Some(t) = As::<dyn OnOff>::cast_mut(self) {
t.set_on(*on).await?;
} else {
return Err(DeviceError::ActionNotAvailable.into());
}
}
CommandType::ActivateScene { deactivate } => {
if let Some(scene) = As::<dyn Scene>::cast(self) {
scene.set_active(!deactivate).await?;
if let Some(t) = As::<dyn Scene>::cast(self) {
t.set_active(!deactivate).await?;
} else {
return Err(DeviceError::ActionNotAvailable.into());
}
}
CommandType::SetFanSpeed { fan_speed } => {
if let Some(t) = As::<dyn FanSpeed>::cast(self) {
t.set_speed(fan_speed).await?;
}
}
}
Ok(())

View File

@@ -20,13 +20,15 @@ pub struct Device {
// customData
}
#[derive(Debug, Deserialize, Clone, Copy)]
#[derive(Debug, Deserialize, Clone)]
#[serde(tag = "command", content = "params")]
pub enum CommandType {
#[serde(rename = "action.devices.commands.OnOff")]
OnOff { on: bool },
#[serde(rename = "action.devices.commands.ActivateScene")]
ActivateScene { deactivate: bool },
#[serde(rename = "action.devices.commands.SetFanSpeed")]
SetFanSpeed { fan_speed: String },
}
#[cfg(test)]

View File

@@ -33,4 +33,7 @@ pub enum ResponsePayload {
pub struct State {
#[serde(skip_serializing_if = "Option::is_none")]
pub on: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub current_fan_speed_setting: Option<String>,
}

View File

@@ -96,7 +96,10 @@ mod tests {
fn serialize() {
let mut execute_resp = Payload::new();
let state = State { on: Some(true) };
let state = State {
on: Some(true),
current_fan_speed_setting: None,
};
let mut command = Command::new(Status::Success);
command.states = Some(States {
online: true,

View File

@@ -9,6 +9,8 @@ pub enum Trait {
OnOff,
#[serde(rename = "action.devices.traits.Scene")]
Scene,
#[serde(rename = "action.devices.traits.FanSpeed")]
FanSpeed,
}
#[async_trait]
@@ -36,3 +38,37 @@ pub trait Scene {
async fn set_active(&self, activate: bool) -> Result<(), ErrorCode>;
}
#[derive(Debug, Serialize)]
pub struct SpeedValues {
pub speed_synonym: Vec<String>,
pub lang: String,
}
#[derive(Debug, Serialize)]
pub struct Speed {
pub speed_name: String,
pub speed_values: Vec<SpeedValues>,
}
#[derive(Debug, Serialize)]
pub struct AvailableSpeeds {
pub speeds: Vec<Speed>,
pub ordered: bool,
}
#[async_trait]
#[impl_cast::device_trait]
pub trait FanSpeed {
fn reversible(&self) -> Option<bool> {
None
}
fn command_only_fan_speed(&self) -> Option<bool> {
None
}
fn available_speeds(&self) -> AvailableSpeeds;
async fn current_speed(&self) -> String;
async fn set_speed(&self, speed: &str) -> Result<(), ErrorCode>;
}

View File

@@ -10,4 +10,6 @@ pub enum Type {
Light,
#[serde(rename = "action.devices.types.SCENE")]
Scene,
#[serde(rename = "action.devices.types.AIRPURIFIER")]
AirPurifier,
}