feat: input_number signal support, implement Clone for a lot of error types

This commit is contained in:
2026-07-14 22:53:42 -04:00
parent 38c30d87d0
commit e3c54a996e
10 changed files with 196 additions and 32 deletions

View File

@@ -0,0 +1,16 @@
use pyo3::FromPyObject;
use super::InputNumberMode;
#[derive(Debug, FromPyObject)]
#[pyo3(from_item_all)]
pub struct InputNumberAttributes {
initial: Option<f64>,
editable: bool,
min: f64,
max: f64,
step: f64,
mode: InputNumberMode,
// todo: CustomUnitOfMeasurement type? probably not?
unit_of_measurement: Option<String>,
}

View File

@@ -1 +1,73 @@
use std::{future::Future, sync::Arc};
use emitter_and_signal::{Signal, SignalExt};
use pyo3::{Py, PyAny, PyErr, Python};
use snafu::{ResultExt, Snafu};
use crate::{
domain::Domain,
entity_id::EntityId,
home_assistant::HomeAssistant,
object_id::ObjectId,
state::HomeAssistantState,
state_object::{self, StateObject, StateObjectSignalError},
};
mod attributes;
mod mode;
pub use attributes::InputNumberAttributes;
pub use mode::InputNumberMode;
#[derive(Debug, Snafu)]
pub enum CreateSignalError {
/// couldn't get the underlying state object signal
StateObjectSignalError {
source: state_object::CreateSignalError,
},
/// couldn't map the state object to a power value
MappedSignalError {
source: emitter_and_signal::signal_ext::ProducerAlreadyExited,
},
}
pub fn signal<'py>(
py: Python<'py>,
home_assistant: &'py HomeAssistant,
object_id: ObjectId,
) -> Result<
(
Signal<Option<Arc<Result<HomeAssistantState<f64>, StateObjectSignalError<Arc<PyErr>>>>>>,
impl Future<Output = Result<(), emitter_and_signal::signal::JoinError>>,
),
CreateSignalError,
> {
let entity_id = EntityId(Domain::InputNumber, object_id);
let (signal, task1) =
StateObject::<HomeAssistantState<f64>, InputNumberAttributes, Py<PyAny>>::signal(
py,
home_assistant,
entity_id,
)
.context(StateObjectSignalSnafu)?;
let (signal, task2) = signal
.map(|state_object_arc_result_option| {
state_object_arc_result_option.map(|state_object_arc_result| {
Arc::new(
(&*state_object_arc_result)
.as_ref()
.map(|state_object| state_object.state.clone())
.map_err(|e| e.clone()),
)
})
})
.context(MappedSignalSnafu)?;
Ok((
signal,
async move { tokio::try_join!(task1, task2).map(|_| ()) },
))
}

View File

@@ -0,0 +1,10 @@
use python_utils::{FromPyFromStr, ToStrToPy};
use strum::EnumString;
#[derive(Debug, Clone, Default, EnumString, strum::Display, FromPyFromStr, ToStrToPy)]
#[strum(serialize_all = "snake_case")]
pub enum InputNumberMode {
Box,
#[default]
Slider,
}