diff --git a/home-assistant/Cargo.toml b/home-assistant/Cargo.toml index 830d05d..c0d790d 100644 --- a/home-assistant/Cargo.toml +++ b/home-assistant/Cargo.toml @@ -26,7 +26,7 @@ pyo3-async-runtimes = { workspace = true, features = ["tokio-runtime"] } python-utils = { path = "../python-utils" } smol_str = "0.3.2" snafu = { workspace = true } -strum = { version = "0.27.1", features = ["derive"] } +strum = { workspace = true, features = ["derive"] } tokio = { workspace = true } tracing = { optional = true, workspace = true } ulid = "1.2.0" diff --git a/home-assistant/src/light/protocol.rs b/home-assistant/src/light/protocol.rs index d11eca2..4b79e19 100644 --- a/home-assistant/src/light/protocol.rs +++ b/home-assistant/src/light/protocol.rs @@ -4,105 +4,73 @@ use crate::{ event::context::context::Context, state::{ErrorState, HomeAssistantState, UnexpectedState}, }; -use arbitrary_value::arbitrary::Arbitrary; -use protocol::light::Light; +use protocol::light::{GetState, SetState}; use pyo3::prelude::*; +use python_utils::IsNone; use snafu::{ResultExt, Snafu}; #[derive(Debug, Snafu)] -pub enum IsStateError { +pub enum GetStateError { GetStateObjectError { source: GetStateObjectError }, Error { state: ErrorState }, UnexpectedError { state: UnexpectedState }, } -impl Light for HomeAssistantLight { - type IsOnError = IsStateError; +impl GetState for HomeAssistantLight { + type Error = GetStateError; - async fn is_on(&self) -> Result { + async fn get_state(&self) -> Result { let state_object = self.get_state_object().context(GetStateObjectSnafu)?; let state = state_object.state; match state { - HomeAssistantState::Ok(light_state) => Ok(matches!(light_state, LightState::On)), - HomeAssistantState::Err(state) => Err(IsStateError::Error { state }), + HomeAssistantState::Ok(light_state) => Ok(light_state.into()), + HomeAssistantState::Err(error_state) => { + Err(GetStateError::Error { state: error_state }) + } HomeAssistantState::UnexpectedErr(state) => { - Err(IsStateError::UnexpectedError { state }) + Err(GetStateError::UnexpectedError { state }) } } } - - type IsOffError = IsStateError; - - async fn is_off(&self) -> Result { - let state_object = self.get_state_object().context(GetStateObjectSnafu)?; - let state = state_object.state; - - match state { - HomeAssistantState::Ok(light_state) => Ok(matches!(light_state, LightState::Off)), - HomeAssistantState::Err(state) => Err(IsStateError::Error { state }), - HomeAssistantState::UnexpectedErr(state) => { - Err(IsStateError::UnexpectedError { state }) - } - } - } - - type TurnOnError = PyErr; - - async fn turn_on(&mut self) -> Result<(), Self::TurnOnError> { - let context: Option> = None; - let target: Option<()> = None; - - let services = Python::with_gil(|py| self.home_assistant.services(py))?; - // TODO - let service_response: Arbitrary = services - .call_service( - TurnOn { - entity_id: self.entity_id(), - }, - context, - target, - false, - ) - .await?; - - // TODO - #[cfg(feature = "tracing")] - tracing::info!(?service_response); - - Ok(()) - } - - type TurnOffError = PyErr; - - async fn turn_off(&mut self) -> Result<(), Self::TurnOffError> { - let context: Option> = None; - let target: Option<()> = None; - - let services = Python::with_gil(|py| self.home_assistant.services(py))?; - // TODO - let service_response: Arbitrary // TODO: a type that validates as None - = services - .call_service( - TurnOff { - entity_id: self.entity_id(), - }, - context, - target, - false, - ) - .await?; - - // TODO - #[cfg(feature = "tracing")] - tracing::info!(?service_response); - - Ok(()) - } - - type ToggleError = PyErr; - - async fn toggle(&mut self) -> Result<(), Self::ToggleError> { - todo!() - } +} + +impl SetState for HomeAssistantLight { + type Error = PyErr; + + async fn set_state(&mut self, state: protocol::light::State) -> Result<(), Self::Error> { + let context: Option> = None; + let target: Option<()> = None; + + let services = Python::with_gil(|py| self.home_assistant.services(py))?; + + let _: IsNone = match state { + protocol::light::State::Off => { + services + .call_service( + TurnOff { + entity_id: self.entity_id(), + }, + context, + target, + false, + ) + .await + } + protocol::light::State::On => { + services + .call_service( + TurnOn { + entity_id: self.entity_id(), + }, + context, + target, + false, + ) + .await + } + }?; + + Ok(()) + } } diff --git a/home-assistant/src/light/state.rs b/home-assistant/src/light/state.rs index bb418c4..13d8511 100644 --- a/home-assistant/src/light/state.rs +++ b/home-assistant/src/light/state.rs @@ -20,3 +20,21 @@ impl<'py> FromPyObject<'py> for LightState { Ok(state) } } + +impl From for protocol::light::State { + fn from(light_state: LightState) -> Self { + match light_state { + LightState::On => protocol::light::State::On, + LightState::Off => protocol::light::State::Off, + } + } +} + +impl From for LightState { + fn from(state: protocol::light::State) -> Self { + match state { + protocol::light::State::On => LightState::On, + protocol::light::State::Off => LightState::Off, + } + } +}