chore: extract python_utils and home-assistant to their own crates

This commit is contained in:
2025-04-21 21:26:14 -04:00
parent e4fd9844cc
commit f8b269b6ce
36 changed files with 76 additions and 40 deletions

View File

@@ -4,7 +4,9 @@ members = [
"driver/kasa", "driver/kasa",
"emitter-and-signal", "emitter-and-signal",
"entrypoint", "entrypoint",
"home-assistant",
"protocol", "protocol",
"python-utils",
] ]
resolver = "2" resolver = "2"
@@ -12,7 +14,7 @@ resolver = "2"
backoff = "0.4.0" backoff = "0.4.0"
chrono = "0.4.40" chrono = "0.4.40"
chrono-tz = "0.10.1" chrono-tz = "0.10.1"
deranged = "0.4.1" deranged = "0.4"
derive_more = "2.0.1" derive_more = "2.0.1"
snafu = "0.8.5" snafu = "0.8.5"
tokio = "1.32.0" tokio = "1.32.0"

View File

@@ -19,32 +19,19 @@ axum = { version = "0.8.1", default-features = false, features = [
chrono = { workspace = true } chrono = { workspace = true }
chrono-tz = { workspace = true } chrono-tz = { workspace = true }
deranged = { workspace = true, features = ["serde"] } deranged = { workspace = true, features = ["serde"] }
derive_more = { workspace = true, features = [
"display",
"from",
"from_str",
"into",
"try_from",
"try_into",
] }
driver-kasa = { path = "../driver/kasa" } driver-kasa = { path = "../driver/kasa" }
emitter-and-signal = { path = "../emitter-and-signal" } emitter-and-signal = { path = "../emitter-and-signal" }
home-assistant = { path = "../home-assistant" }
im = { version = "15.1.0", features = ["rayon"] } im = { version = "15.1.0", features = ["rayon"] }
once_cell = "1.21.3"
protocol = { path = "../protocol" } protocol = { path = "../protocol" }
pyo3 = { workspace = true, features = [ pyo3 = { workspace = true, features = [
"auto-initialize", "auto-initialize",
"chrono", "chrono",
"extension-module", "extension-module",
] } ] }
pyo3-async-runtimes = { workspace = true, features = [ pyo3-async-runtimes = { workspace = true, features = ["tokio-runtime"] }
"attributes",
"tokio-runtime",
] }
shadow-rs = { version = "1.0.1", default-features = false } shadow-rs = { version = "1.0.1", default-features = false }
smol_str = "0.3.2"
snafu = { workspace = true } snafu = { workspace = true }
strum = { version = "0.27.1", features = ["derive"] }
tokio = { workspace = true, features = [ tokio = { workspace = true, features = [
"macros", "macros",
"rt", "rt",
@@ -55,7 +42,6 @@ tokio = { workspace = true, features = [
tracing = { workspace = true } tracing = { workspace = true }
tracing-appender = "0.2.3" tracing-appender = "0.2.3"
tracing-subscriber = "0.3.17" tracing-subscriber = "0.3.17"
ulid = "1.2.0"
uom = "0.36.0" uom = "0.36.0"
[build-dependencies] [build-dependencies]

View File

@@ -18,8 +18,6 @@ use tracing_subscriber::{
}; };
use tracing_to_home_assistant::TracingToHomeAssistant; use tracing_to_home_assistant::TracingToHomeAssistant;
mod home_assistant;
mod python_utils;
mod tracing_to_home_assistant; mod tracing_to_home_assistant;
shadow!(build_info); shadow!(build_info);

View File

@@ -7,7 +7,7 @@ use tracing::{
}; };
use tracing_subscriber::{layer::Context, Layer}; use tracing_subscriber::{layer::Context, Layer};
use crate::home_assistant::logger::{HassLogger, LogData}; use home_assistant::logger::{HassLogger, LogData};
pub struct TracingToHomeAssistant; pub struct TracingToHomeAssistant;

32
home-assistant/Cargo.toml Normal file
View File

@@ -0,0 +1,32 @@
[package]
name = "home-assistant"
version = "0.1.0"
edition = "2021"
[features]
tracing = ["dep:tracing"]
[dependencies]
arbitrary-value = { path = "../arbitrary-value" }
chrono = { workspace = true }
chrono-tz = { workspace = true }
derive_more = { workspace = true, features = [
"display",
"from",
"from_str",
"into",
"try_from",
"try_into",
] }
emitter-and-signal = { path = "../emitter-and-signal" }
once_cell = "1.21.3"
protocol = { path = "../protocol" }
pyo3 = { workspace = true }
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"] }
tokio = { workspace = true }
tracing = { optional = true, workspace = true }
ulid = "1.2.0"

View File

@@ -1,7 +1,7 @@
use pyo3::exceptions::PyValueError; use pyo3::exceptions::PyValueError;
use pyo3::prelude::*; use pyo3::prelude::*;
use crate::home_assistant::{entity_id::EntityId, state_object::StateObject}; use crate::{entity_id::EntityId, state_object::StateObject};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Type; pub struct Type;

View File

@@ -2,7 +2,7 @@ use std::convert::Infallible;
use pyo3::prelude::*; use pyo3::prelude::*;
use crate::python_utils::{detach, validate_type_by_name}; use python_utils::{detach, validate_type_by_name};
use super::{service_registry::ServiceRegistry, state_machine::StateMachine}; use super::{service_registry::ServiceRegistry, state_machine::StateMachine};

View File

@@ -3,7 +3,7 @@ use pyo3::prelude::*;
use snafu::{ResultExt, Snafu}; use snafu::{ResultExt, Snafu};
use state::LightState; use state::LightState;
use crate::home_assistant::state::HomeAssistantState; use crate::state::HomeAssistantState;
use super::{ use super::{
domain::Domain, entity_id::EntityId, home_assistant::HomeAssistant, object_id::ObjectId, domain::Domain, entity_id::EntityId, home_assistant::HomeAssistant, object_id::ObjectId,

View File

@@ -1,6 +1,6 @@
use super::service::{turn_off::TurnOff, turn_on::TurnOn}; use super::service::{turn_off::TurnOff, turn_on::TurnOn};
use super::{state::LightState, GetStateObjectError, HomeAssistantLight}; use super::{state::LightState, GetStateObjectError, HomeAssistantLight};
use crate::home_assistant::{ use crate::{
event::context::context::Context, event::context::context::Context,
state::{ErrorState, HomeAssistantState, UnexpectedState}, state::{ErrorState, HomeAssistantState, UnexpectedState},
}; };
@@ -67,6 +67,7 @@ impl Light for HomeAssistantLight {
.await?; .await?;
// TODO // TODO
#[cfg(feature = "tracing")]
tracing::info!(?service_response); tracing::info!(?service_response);
Ok(()) Ok(())
@@ -92,6 +93,10 @@ impl Light for HomeAssistantLight {
) )
.await?; .await?;
// TODO
#[cfg(feature = "tracing")]
tracing::info!(?service_response);
Ok(()) Ok(())
} }

View File

@@ -2,7 +2,7 @@ use std::str::FromStr;
use pyo3::IntoPyObject; use pyo3::IntoPyObject;
use crate::home_assistant::{ use crate::{
entity_id::EntityId, entity_id::EntityId,
service::{service_domain::ServiceDomain, service_id::ServiceId, IntoServiceCall}, service::{service_domain::ServiceDomain, service_id::ServiceId, IntoServiceCall},
}; };

View File

@@ -1,8 +1,8 @@
use std::{convert::Infallible, str::FromStr}; use std::str::FromStr;
use pyo3::IntoPyObject; use pyo3::IntoPyObject;
use crate::home_assistant::{ use crate::{
entity_id::EntityId, entity_id::EntityId,
service::{service_domain::ServiceDomain, service_id::ServiceId, IntoServiceCall}, service::{service_domain::ServiceDomain, service_id::ServiceId, IntoServiceCall},
}; };

View File

@@ -1,7 +1,7 @@
use crate::python_utils::{detach, validate_type_by_name};
use arbitrary_value::{arbitrary::Arbitrary, map::Map}; use arbitrary_value::{arbitrary::Arbitrary, map::Map};
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use pyo3::{prelude::*, types::PyTuple}; use pyo3::{prelude::*, types::PyTuple};
use python_utils::{detach, validate_type_by_name};
#[derive(Debug)] #[derive(Debug)]
pub struct HassLogger(Py<PyAny>); pub struct HassLogger(Py<PyAny>);

View File

@@ -1,8 +1,6 @@
use pyo3::prelude::*;
use crate::python_utils::{detach, validate_type_by_name};
use super::{event::context::context::Context, service::IntoServiceCall}; use super::{event::context::context::Context, service::IntoServiceCall};
use pyo3::prelude::*;
use python_utils::{detach, validate_type_by_name};
#[derive(Debug)] #[derive(Debug)]
pub struct ServiceRegistry(Py<PyAny>); pub struct ServiceRegistry(Py<PyAny>);

View File

@@ -1,11 +1,7 @@
use pyo3::prelude::*; use super::entity_id::EntityId;
use crate::{
home_assistant::entity_id::EntityId,
python_utils::{detach, validate_type_by_name},
};
use super::state_object::StateObject; use super::state_object::StateObject;
use pyo3::prelude::*;
use python_utils::{detach, validate_type_by_name};
#[derive(Debug)] #[derive(Debug)]
pub struct StateMachine(Py<PyAny>); pub struct StateMachine(Py<PyAny>);

View File

@@ -2,7 +2,7 @@ use super::{
event::{context::context::Context, specific::state_changed}, event::{context::context::Context, specific::state_changed},
home_assistant::HomeAssistant, home_assistant::HomeAssistant,
}; };
use crate::home_assistant::entity_id::EntityId; use crate::entity_id::EntityId;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use emitter_and_signal::signal::Signal; use emitter_and_signal::signal::Signal;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
@@ -62,6 +62,7 @@ impl<
let callback = let callback =
move |args: &Bound<'_, PyTuple>, move |args: &Bound<'_, PyTuple>,
_kwargs: Option<&Bound<'_, PyDict>>| { _kwargs: Option<&Bound<'_, PyDict>>| {
#[cfg(feature = "tracing")]
tracing::debug!("calling the closure"); tracing::debug!("calling the closure");
if let Ok((event,)) = args.extract::<( if let Ok((event,)) = args.extract::<(
@@ -77,6 +78,7 @@ impl<
)>() { )>() {
let new_state = event.data.new_state; let new_state = event.data.new_state;
#[cfg(feature = "tracing")]
tracing::debug!("sending a new state"); // TODO: remove tracing::debug!("sending a new state"); // TODO: remove
new_state_sender.try_send(new_state).unwrap(); new_state_sender.try_send(new_state).unwrap();
} }
@@ -89,38 +91,47 @@ impl<
); );
event_module.call_method1("async_track_state_change_event", args)? event_module.call_method1("async_track_state_change_event", args)?
}; };
#[cfg(feature = "tracing")]
tracing::debug!(?untrack, "as any"); tracing::debug!(?untrack, "as any");
let is_callable = untrack.is_callable(); let is_callable = untrack.is_callable();
#[cfg(feature = "tracing")]
tracing::debug!(?is_callable); tracing::debug!(?is_callable);
// let untrack = untrack.downcast_into::<PyFunction>()?; // let untrack = untrack.downcast_into::<PyFunction>()?;
// tracing::debug!(?untrack, "as downcast"); // tracing::debug!(?untrack, "as downcast");
let untrack = untrack.unbind(); let untrack = untrack.unbind();
#[cfg(feature = "tracing")]
tracing::debug!(?untrack, "as unbound"); tracing::debug!(?untrack, "as unbound");
Ok(untrack) Ok(untrack)
}); });
if let Ok(untrack) = untrack { if let Ok(untrack) = untrack {
#[cfg(feature = "tracing")]
tracing::debug!("untrack is ok, going to wait for the next relevant event..."); tracing::debug!("untrack is ok, going to wait for the next relevant event...");
loop { loop {
select! { select! {
biased; biased;
_ = publisher.all_unsubscribed() => { _ = publisher.all_unsubscribed() => {
#[cfg(feature = "tracing")]
tracing::debug!("calling untrack"); tracing::debug!("calling untrack");
let res = Python::with_gil(|py| untrack.call0(py)); let res = Python::with_gil(|py| untrack.call0(py));
#[cfg(feature = "tracing")]
tracing::debug!(?res); tracing::debug!(?res);
break; break;
} }
new_state = new_state_receiver.recv() => { new_state = new_state_receiver.recv() => {
match new_state { match new_state {
Some(new_state) => { Some(new_state) => {
#[cfg(feature = "tracing")]
tracing::debug!("publishing new state"); tracing::debug!("publishing new state");
publisher.publish(new_state.map(Arc::new)) publisher.publish(new_state.map(Arc::new))
}, },
None => { None => {
#[cfg(feature = "tracing")]
tracing::debug!("channel dropped"); tracing::debug!("channel dropped");
break break
}, },
@@ -129,6 +140,7 @@ impl<
} }
} }
} else { } else {
#[cfg(feature = "tracing")]
tracing::debug!("untrack is err"); tracing::debug!("untrack is err");
} }
} }

7
python-utils/Cargo.toml Normal file
View File

@@ -0,0 +1,7 @@
[package]
name = "python-utils"
version = "0.1.0"
edition = "2021"
[dependencies]
pyo3 = { workspace = true }