chore+feat(home-assistant): update to pyo3 0.27 and update extraction errors, switch out SmolStr for Arc<str>, tighten up light service calls and implement some for notify, start implementing units of measurement like for power
This commit is contained in:
1
home-assistant/src/unit_of_measurement/mod.rs
Normal file
1
home-assistant/src/unit_of_measurement/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod power;
|
||||
102
home-assistant/src/unit_of_measurement/power.rs
Normal file
102
home-assistant/src/unit_of_measurement/power.rs
Normal file
@@ -0,0 +1,102 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use pyo3::{
|
||||
exceptions::{PyException, PyValueError},
|
||||
prelude::*,
|
||||
};
|
||||
use snafu::{ResultExt, Snafu};
|
||||
use strum::EnumString;
|
||||
use uom::{
|
||||
si::{
|
||||
energy::btu,
|
||||
power::{gigawatt, kilowatt, megawatt, milliwatt, terawatt, watt},
|
||||
quantities::{Energy, Power, Time},
|
||||
time::hour,
|
||||
Units, SI,
|
||||
},
|
||||
Conversion,
|
||||
};
|
||||
|
||||
/// Power units
|
||||
#[derive(Debug, Clone, Copy, EnumString, strum::Display)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum UnitOfMeasurement {
|
||||
#[strum(serialize = "mW")]
|
||||
MilliWatt,
|
||||
#[strum(serialize = "W")]
|
||||
Watt,
|
||||
#[strum(serialize = "kW")]
|
||||
KiloWatt,
|
||||
#[strum(serialize = "MW")]
|
||||
MegaWatt,
|
||||
#[strum(serialize = "GW")]
|
||||
GigaWatt,
|
||||
#[strum(serialize = "TW")]
|
||||
TeraWatt,
|
||||
#[strum(serialize = "BTU/h")]
|
||||
BtuPerhour,
|
||||
}
|
||||
|
||||
#[derive(Debug, Snafu)]
|
||||
pub enum ExtractUnitOfMeasurementError {
|
||||
/// couldn't extract the object as a string
|
||||
ExtractStringError { source: PyErr },
|
||||
|
||||
/// couldn't parse the string as a [`UnitOfMeasurement`]
|
||||
ParseError {
|
||||
source: <UnitOfMeasurement as FromStr>::Err,
|
||||
},
|
||||
}
|
||||
|
||||
impl From<ExtractUnitOfMeasurementError> for PyErr {
|
||||
fn from(error: ExtractUnitOfMeasurementError) -> Self {
|
||||
match &error {
|
||||
ExtractUnitOfMeasurementError::ExtractStringError { .. } => {
|
||||
PyException::new_err(error.to_string())
|
||||
}
|
||||
ExtractUnitOfMeasurementError::ParseError { .. } => {
|
||||
PyValueError::new_err(error.to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: replace with a derive(PyFromStr) (analogous to serde_with::DeserializeFromStr) once I make one
|
||||
impl<'a, 'py> FromPyObject<'a, 'py> for UnitOfMeasurement {
|
||||
type Error = ExtractUnitOfMeasurementError;
|
||||
|
||||
fn extract(obj: Borrowed<'a, 'py, PyAny>) -> Result<Self, Self::Error> {
|
||||
let s = obj.extract().context(ExtractStringSnafu)?;
|
||||
let unit_of_measurement = UnitOfMeasurement::from_str(s).context(ParseSnafu)?;
|
||||
|
||||
Ok(unit_of_measurement)
|
||||
}
|
||||
}
|
||||
|
||||
impl UnitOfMeasurement {
|
||||
pub fn into_uom<V>(&self, amount: V) -> Power<V>
|
||||
where
|
||||
V: uom::num::Num + uom::Conversion<V, T = V>,
|
||||
milliwatt: Conversion<V, T = V>,
|
||||
watt: Conversion<V, T = V>,
|
||||
kilowatt: Conversion<V, T = V>,
|
||||
megawatt: Conversion<V, T = V>,
|
||||
gigawatt: Conversion<V, T = V>,
|
||||
terawatt: Conversion<V, T = V>,
|
||||
btu: Conversion<V, T = V>,
|
||||
hour: Conversion<V, T = V>,
|
||||
SI<V>: Units<V>,
|
||||
{
|
||||
match self {
|
||||
UnitOfMeasurement::MilliWatt => Power::new::<milliwatt>(amount),
|
||||
UnitOfMeasurement::Watt => Power::new::<watt>(amount),
|
||||
UnitOfMeasurement::KiloWatt => Power::new::<kilowatt>(amount),
|
||||
UnitOfMeasurement::MegaWatt => Power::new::<megawatt>(amount),
|
||||
UnitOfMeasurement::GigaWatt => Power::new::<gigawatt>(amount),
|
||||
UnitOfMeasurement::TeraWatt => Power::new::<terawatt>(amount),
|
||||
UnitOfMeasurement::BtuPerhour => {
|
||||
Energy::new::<btu>(amount) / Time::new::<hour>(V::one())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user