chore(home-assistant): implement the revised light protocol
This commit is contained in:
@@ -26,7 +26,7 @@ pyo3-async-runtimes = { workspace = true, features = ["tokio-runtime"] }
|
|||||||
python-utils = { path = "../python-utils" }
|
python-utils = { path = "../python-utils" }
|
||||||
smol_str = "0.3.2"
|
smol_str = "0.3.2"
|
||||||
snafu = { workspace = true }
|
snafu = { workspace = true }
|
||||||
strum = { version = "0.27.1", features = ["derive"] }
|
strum = { workspace = true, features = ["derive"] }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
tracing = { optional = true, workspace = true }
|
tracing = { optional = true, workspace = true }
|
||||||
ulid = "1.2.0"
|
ulid = "1.2.0"
|
||||||
|
@@ -4,85 +4,49 @@ use crate::{
|
|||||||
event::context::context::Context,
|
event::context::context::Context,
|
||||||
state::{ErrorState, HomeAssistantState, UnexpectedState},
|
state::{ErrorState, HomeAssistantState, UnexpectedState},
|
||||||
};
|
};
|
||||||
use arbitrary_value::arbitrary::Arbitrary;
|
use protocol::light::{GetState, SetState};
|
||||||
use protocol::light::Light;
|
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
|
use python_utils::IsNone;
|
||||||
use snafu::{ResultExt, Snafu};
|
use snafu::{ResultExt, Snafu};
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
pub enum IsStateError {
|
pub enum GetStateError {
|
||||||
GetStateObjectError { source: GetStateObjectError },
|
GetStateObjectError { source: GetStateObjectError },
|
||||||
Error { state: ErrorState },
|
Error { state: ErrorState },
|
||||||
UnexpectedError { state: UnexpectedState },
|
UnexpectedError { state: UnexpectedState },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Light for HomeAssistantLight {
|
impl GetState for HomeAssistantLight {
|
||||||
type IsOnError = IsStateError;
|
type Error = GetStateError;
|
||||||
|
|
||||||
async fn is_on(&self) -> Result<bool, Self::IsOnError> {
|
async fn get_state(&self) -> Result<protocol::light::State, Self::Error> {
|
||||||
let state_object = self.get_state_object().context(GetStateObjectSnafu)?;
|
let state_object = self.get_state_object().context(GetStateObjectSnafu)?;
|
||||||
let state = state_object.state;
|
let state = state_object.state;
|
||||||
|
|
||||||
match state {
|
match state {
|
||||||
HomeAssistantState::Ok(light_state) => Ok(matches!(light_state, LightState::On)),
|
HomeAssistantState::Ok(light_state) => Ok(light_state.into()),
|
||||||
HomeAssistantState::Err(state) => Err(IsStateError::Error { state }),
|
HomeAssistantState::Err(error_state) => {
|
||||||
|
Err(GetStateError::Error { state: error_state })
|
||||||
|
}
|
||||||
HomeAssistantState::UnexpectedErr(state) => {
|
HomeAssistantState::UnexpectedErr(state) => {
|
||||||
Err(IsStateError::UnexpectedError { state })
|
Err(GetStateError::UnexpectedError { state })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type IsOffError = IsStateError;
|
impl SetState for HomeAssistantLight {
|
||||||
|
type Error = PyErr;
|
||||||
|
|
||||||
async fn is_off(&self) -> Result<bool, Self::IsOffError> {
|
async fn set_state(&mut self, state: protocol::light::State) -> Result<(), Self::Error> {
|
||||||
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<Context<()>> = None;
|
let context: Option<Context<()>> = None;
|
||||||
let target: Option<()> = None;
|
let target: Option<()> = None;
|
||||||
|
|
||||||
let services = Python::with_gil(|py| self.home_assistant.services(py))?;
|
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
|
let _: IsNone = match state {
|
||||||
#[cfg(feature = "tracing")]
|
protocol::light::State::Off => {
|
||||||
tracing::info!(?service_response);
|
services
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
type TurnOffError = PyErr;
|
|
||||||
|
|
||||||
async fn turn_off(&mut self) -> Result<(), Self::TurnOffError> {
|
|
||||||
let context: Option<Context<()>> = 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(
|
.call_service(
|
||||||
TurnOff {
|
TurnOff {
|
||||||
entity_id: self.entity_id(),
|
entity_id: self.entity_id(),
|
||||||
@@ -91,18 +55,22 @@ impl Light for HomeAssistantLight {
|
|||||||
target,
|
target,
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
.await?;
|
.await
|
||||||
|
}
|
||||||
// TODO
|
protocol::light::State::On => {
|
||||||
#[cfg(feature = "tracing")]
|
services
|
||||||
tracing::info!(?service_response);
|
.call_service(
|
||||||
|
TurnOn {
|
||||||
|
entity_id: self.entity_id(),
|
||||||
|
},
|
||||||
|
context,
|
||||||
|
target,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
type ToggleError = PyErr;
|
|
||||||
|
|
||||||
async fn toggle(&mut self) -> Result<(), Self::ToggleError> {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -20,3 +20,21 @@ impl<'py> FromPyObject<'py> for LightState {
|
|||||||
Ok(state)
|
Ok(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<LightState> 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<protocol::light::State> for LightState {
|
||||||
|
fn from(state: protocol::light::State) -> Self {
|
||||||
|
match state {
|
||||||
|
protocol::light::State::On => LightState::On,
|
||||||
|
protocol::light::State::Off => LightState::Off,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user