Compare commits

...

2 Commits

7 changed files with 30 additions and 32 deletions

2
Cargo.lock generated
View File

@@ -842,7 +842,7 @@ checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
[[package]] [[package]]
name = "smart-home-in-rust-with-home-assistant" name = "smart-home-in-rust-with-home-assistant"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"chrono-tz", "chrono-tz",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "smart-home-in-rust-with-home-assistant" name = "smart-home-in-rust-with-home-assistant"
version = "0.1.0" version = "0.2.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -11,7 +11,13 @@ crate-type = ["cdylib"]
[dependencies] [dependencies]
chrono = "0.4.40" chrono = "0.4.40"
chrono-tz = "0.10.1" chrono-tz = "0.10.1"
derive_more = { version = "2.0.1", features = ["display", "from", "into", "try_from", "try_into"] } derive_more = { version = "2.0.1", features = [
"display",
"from",
"into",
"try_from",
"try_into",
] }
ijson = "0.1.4" ijson = "0.1.4"
itertools = "0.14.0" itertools = "0.14.0"
pyo3 = { version = "0.23.0", features = ["chrono"] } pyo3 = { version = "0.23.0", features = ["chrono"] }

View File

@@ -1,24 +1,14 @@
use pyo3::prelude::*; use pyo3::prelude::*;
use crate::home_assistant::event::event::Event;
use super::id::Id; use super::id::Id;
/// The context that triggered something. /// The context that triggered something.
#[derive(Debug, FromPyObject)] #[derive(Debug, FromPyObject)]
pub struct Context { pub struct Context<Event> {
pub id: Id, pub id: Id,
pub user_id: Option<String>, pub user_id: Option<String>,
pub parent_id: Option<String>, pub parent_id: Option<String>,
/// In order to prevent cycles, the user must extract this to an [`Event<Arbitrary>`](super::event::Event) themself (or even specify a specific type parameter!) /// In order to prevent cycles, the user must decide to pass [`Py<PyAny>`] for the `Event` type here
origin_event: Py<PyAny>, /// or for the `Context` type in [`Event`]
} pub origin_event: Event,
impl Context {
pub fn origin_event<'py, Type: FromPyObject<'py>, Data: FromPyObject<'py>>(
&self,
py: Python<'py>,
) -> PyResult<Event<Type, Data>> {
self.origin_event.extract(py)
}
} }

View File

@@ -5,20 +5,17 @@ use super::{context::context::Context, event_origin::EventOrigin};
/// Representation of an event within the bus. /// Representation of an event within the bus.
#[derive(Debug, FromPyObject)] #[derive(Debug, FromPyObject)]
pub struct Event<Type, Data> { pub struct Event<Type, Data, Context> {
pub event_type: Type, pub event_type: Type,
pub data: Data, pub data: Data,
pub origin: EventOrigin, pub origin: EventOrigin,
/// In order to prevent cycles, the user must extract this to a [`Context`](super::context::Context) themself, using the [`context`](Self::context) method /// In order to prevent cycles, the user must decide to pass [`Py<PyAny>`] for the `Context` type here
context: Py<PyAny>, /// or for the `Event` type in [`Context`]
pub context: Context,
time_fired_timestamp: f64, time_fired_timestamp: f64,
} }
impl<Type, Data> Event<Type, Data> { impl<Type, Data, Context> Event<Type, Data, Context> {
pub fn context<'py>(&self, py: Python<'py>) -> PyResult<Context> {
self.context.extract(py)
}
pub fn time_fired(&self) -> Option<DateTime<Utc>> { pub fn time_fired(&self) -> Option<DateTime<Utc>> {
const NANOS_PER_SEC: i32 = 1_000_000_000; const NANOS_PER_SEC: i32 = 1_000_000_000;

View File

@@ -24,11 +24,12 @@ impl<'py> FromPyObject<'py> for Type {
#[derive(Debug, FromPyObject)] #[derive(Debug, FromPyObject)]
#[pyo3(from_item_all)] #[pyo3(from_item_all)]
pub struct Data { pub struct Data<OldStateContextEvent, NewStateContextEvent> {
pub entity_id: EntityId, pub entity_id: EntityId,
pub old_state: Option<State>, pub old_state: Option<State<OldStateContextEvent>>,
pub new_state: Option<State>, pub new_state: Option<State<NewStateContextEvent>>,
} }
/// A state changed event is fired when on state write the state is changed. /// A state changed event is fired when on state write the state is changed.
pub type Event = super::super::event::Event<Type, Data>; pub type Event<OldStateContextEvent, NewStateContextEvent, Context> =
super::super::event::Event<Type, Data<OldStateContextEvent, NewStateContextEvent>, Context>;

View File

@@ -6,12 +6,12 @@ use crate::{arbitrary::map::Map, home_assistant::entity_id::EntityId};
use super::event::context::context::Context; use super::event::context::context::Context;
#[derive(Debug, FromPyObject)] #[derive(Debug, FromPyObject)]
pub struct State { pub struct State<ContextEvent> {
pub entity_id: EntityId, pub entity_id: EntityId,
pub state: String, pub state: String,
pub attributes: Map, pub attributes: Map,
pub last_changed: Option<DateTime<Utc>>, pub last_changed: Option<DateTime<Utc>>,
pub last_reported: Option<DateTime<Utc>>, pub last_reported: Option<DateTime<Utc>>,
pub last_updated: Option<DateTime<Utc>>, pub last_updated: Option<DateTime<Utc>>,
pub context: Context, pub context: Context<ContextEvent>,
} }

View File

@@ -21,7 +21,11 @@ impl<'py> FromPyObject<'py> for StateMachine {
} }
impl StateMachine { impl StateMachine {
pub fn get(&self, py: &Python, entity_id: EntityId) -> Result<Option<State>, PyErr> { pub fn get<ContextEvent: for<'py> FromPyObject<'py>>(
&self,
py: &Python,
entity_id: EntityId,
) -> Result<Option<State<ContextEvent>>, PyErr> {
let args = (entity_id.to_string(),); let args = (entity_id.to_string(),);
let state = self.0.call_method1(*py, "get", args)?; let state = self.0.call_method1(*py, "get", args)?;
state.extract(*py) state.extract(*py)