1786285862

This commit is contained in:
2026-08-09 16:31:02 +02:00
parent ee6bc810a3
commit 2928f6fc9e
4 changed files with 30 additions and 24 deletions

View File

@@ -6,12 +6,12 @@ use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
use crate::{ use crate::{
error::AppError, error::AppError,
messages::{C2sMessage, S2cMessage}, messages::{CommandMessage, EventMessage},
}; };
pub async fn hass( pub async fn hass(
s2c_tx: UnboundedSender<S2cMessage>, s2c_tx: UnboundedSender<EventMessage>,
mut c2s_rx: UnboundedReceiver<C2sMessage>, mut c2s_rx: UnboundedReceiver<CommandMessage>,
) -> Result<(), AppError> { ) -> Result<(), AppError> {
let Ok(url) = var("HASS_URL") else { let Ok(url) = var("HASS_URL") else {
return Err(AppError::MissingUrl); return Err(AppError::MissingUrl);
@@ -48,7 +48,7 @@ pub async fn hass(
let mut initial_state = state.values().cloned().collect::<Vec<_>>(); let mut initial_state = state.values().cloned().collect::<Vec<_>>();
initial_state.sort_by(|a, b| a.entity_id.cmp(&b.entity_id)); initial_state.sort_by(|a, b| a.entity_id.cmp(&b.entity_id));
s2c_tx.send(S2cMessage::InitialState(initial_state)).ok(); s2c_tx.send(EventMessage::InitialState(initial_state)).ok();
let mut event_receiver = client let mut event_receiver = client
.subscribe_event("state_changed") .subscribe_event("state_changed")
@@ -62,17 +62,17 @@ pub async fn hass(
(None, Some(entity)) => { (None, Some(entity)) => {
// New Entity Added // New Entity Added
state.insert(entity.entity_id.clone(), entity.clone()); state.insert(entity.entity_id.clone(), entity.clone());
s2c_tx.send(S2cMessage::EntityUpdated(entity.clone())).ok(); s2c_tx.send(EventMessage::EntityUpdated(entity.clone())).ok();
} }
(Some(entity), None) => { (Some(entity), None) => {
// Entity Removed // Entity Removed
state.remove(&entity.entity_id); state.remove(&entity.entity_id);
s2c_tx.send(S2cMessage::EntityRemoved(entity.clone())).ok(); s2c_tx.send(EventMessage::EntityRemoved(entity.clone())).ok();
} }
(Some(_), Some(entity)) => { (Some(_), Some(entity)) => {
// Entity Updated // Entity Updated
state.insert(entity.entity_id.clone(), entity.clone()); state.insert(entity.entity_id.clone(), entity.clone());
s2c_tx.send(S2cMessage::EntityUpdated(entity.clone())).ok(); s2c_tx.send(EventMessage::EntityUpdated(entity.clone())).ok();
} }
_ => {} _ => {}
} }
@@ -80,7 +80,7 @@ pub async fn hass(
Some(message) = c2s_rx.recv() => { Some(message) = c2s_rx.recv() => {
if let Err(err) = match message { if let Err(err) = match message {
C2sMessage::ToggleLight { entity_id } => { CommandMessage::ToggleLight { entity_id } => {
if let Some(entity) = state.get(&entity_id) { if let Some(entity) = state.get(&entity_id) {
let payload = json!({ let payload = json!({
"entity_id": entity_id "entity_id": entity_id
@@ -95,7 +95,7 @@ pub async fn hass(
Err(AppError::NoEntity(entity_id)) Err(AppError::NoEntity(entity_id))
} }
} }
C2sMessage::ToggleThermostat { entity_id } => { CommandMessage::ToggleThermostat { entity_id } => {
if let Some(entity) = state.get(&entity_id) { if let Some(entity) = state.get(&entity_id) {
let payload = json!({ let payload = json!({
"entity_id": entity_id "entity_id": entity_id
@@ -110,7 +110,7 @@ pub async fn hass(
Err(AppError::NoEntity(entity_id)) Err(AppError::NoEntity(entity_id))
} }
} }
C2sMessage::SetTemperature { CommandMessage::SetTemperature {
entity_id, entity_id,
temperature, temperature,
} => { } => {

View File

@@ -8,7 +8,10 @@ use tokio::sync::mpsc::unbounded_channel;
use slint::ComponentHandle; use slint::ComponentHandle;
use crate::error::AppError; use crate::{
error::AppError,
messages::{CommandMessage, EventMessage},
};
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), AppError> { async fn main() -> Result<(), AppError> {
@@ -19,8 +22,8 @@ async fn main() -> Result<(), AppError> {
let app = ui::AppWindow::new()?; let app = ui::AppWindow::new()?;
let (c2s_tx, c2s_rx) = unbounded_channel::<messages::C2sMessage>(); let (c2s_tx, c2s_rx) = unbounded_channel::<CommandMessage>();
let (s2c_tx, s2c_rx) = unbounded_channel::<messages::S2cMessage>(); let (s2c_tx, s2c_rx) = unbounded_channel::<EventMessage>();
ui::bind_buttons(&app, c2s_tx); ui::bind_buttons(&app, c2s_tx);

View File

@@ -1,7 +1,7 @@
use hass_rs::HassEntity; use hass_rs::HassEntity;
#[derive(Clone)] #[derive(Clone)]
pub enum C2sMessage { pub enum CommandMessage {
ToggleLight { entity_id: String }, ToggleLight { entity_id: String },
ToggleThermostat { entity_id: String }, ToggleThermostat { entity_id: String },
@@ -10,7 +10,7 @@ pub enum C2sMessage {
} }
#[derive(Clone)] #[derive(Clone)]
pub enum S2cMessage { pub enum EventMessage {
InitialState(Vec<HassEntity>), InitialState(Vec<HassEntity>),
EntityUpdated(HassEntity), EntityUpdated(HassEntity),
EntityRemoved(HassEntity), EntityRemoved(HassEntity),

View File

@@ -2,7 +2,7 @@ slint::include_modules!();
use crate::{ use crate::{
ha_ext::*, ha_ext::*,
messages::{C2sMessage, S2cMessage}, messages::{CommandMessage, EventMessage},
}; };
use hass_rs::HassEntity; use hass_rs::HassEntity;
@@ -109,14 +109,14 @@ pub fn apply_state(app: &Weak<AppWindow>, entities: Vec<HassEntity>) {
} }
} }
pub fn bind_buttons(app: &AppWindow, c2s_tx: UnboundedSender<C2sMessage>) { pub fn bind_buttons(app: &AppWindow, c2s_tx: UnboundedSender<CommandMessage>) {
// Button Bindings // Button Bindings
app.on_toggle_light({ app.on_toggle_light({
let c2s_tx = c2s_tx.clone(); let c2s_tx = c2s_tx.clone();
move |entity_id| { move |entity_id| {
let id = entity_id.to_string(); let id = entity_id.to_string();
if let Err(err) = c2s_tx.send(C2sMessage::ToggleLight { entity_id: id }) { if let Err(err) = c2s_tx.send(CommandMessage::ToggleLight { entity_id: id }) {
eprintln!("Failed to send message to server.\n\t{:?}", err); eprintln!("Failed to send message to server.\n\t{:?}", err);
} }
} }
@@ -125,7 +125,7 @@ pub fn bind_buttons(app: &AppWindow, c2s_tx: UnboundedSender<C2sMessage>) {
app.on_set_temperature({ app.on_set_temperature({
let c2s_tx = c2s_tx.clone(); let c2s_tx = c2s_tx.clone();
move |entity_id, value| { move |entity_id, value| {
if let Err(err) = c2s_tx.send(C2sMessage::SetTemperature { if let Err(err) = c2s_tx.send(CommandMessage::SetTemperature {
entity_id: entity_id.to_string(), entity_id: entity_id.to_string(),
temperature: value, temperature: value,
}) { }) {
@@ -139,23 +139,26 @@ pub fn bind_buttons(app: &AppWindow, c2s_tx: UnboundedSender<C2sMessage>) {
move |entity_id| { move |entity_id| {
let id = entity_id.to_string(); let id = entity_id.to_string();
if let Err(err) = c2s_tx.send(C2sMessage::ToggleThermostat { entity_id: id }) { if let Err(err) = c2s_tx.send(CommandMessage::ToggleThermostat { entity_id: id }) {
eprintln!("Failed to send message to server.\n\t{:?}", err); eprintln!("Failed to send message to server.\n\t{:?}", err);
} }
} }
}); });
} }
pub async fn update_listener(app_weak: Weak<AppWindow>, mut s2c_rx: UnboundedReceiver<S2cMessage>) { pub async fn update_listener(
app_weak: Weak<AppWindow>,
mut s2c_rx: UnboundedReceiver<EventMessage>,
) {
while let Some(message) = s2c_rx.recv().await { while let Some(message) = s2c_rx.recv().await {
match message { match message {
S2cMessage::InitialState(items) => { EventMessage::InitialState(items) => {
apply_state(&app_weak, items); apply_state(&app_weak, items);
} }
S2cMessage::EntityUpdated(hass_entity) => { EventMessage::EntityUpdated(hass_entity) => {
apply_state(&app_weak, vec![hass_entity]); apply_state(&app_weak, vec![hass_entity]);
} }
S2cMessage::EntityRemoved(hass_entity) => { EventMessage::EntityRemoved(hass_entity) => {
apply_state(&app_weak, vec![hass_entity]); apply_state(&app_weak, vec![hass_entity]);
} }
} }