deckster/handlers/home_assistant/src/handler.rs
Moritz Ruth cb119963ce
Remove knobs from the home_assistant handler
I cannot figure out why they're buggy :/
2024-06-20 14:32:02 +02:00

110 lines
3.8 KiB
Rust

use std::thread;
use tokio::select;
use tokio::sync::broadcast;
use tokio::task::LocalSet;
use deckster_mode::shared::handler_communication::{HandlerCommand, HandlerEvent, HandlerInitializationError, InitialHandlerMessage, KeyEvent};
use deckster_mode::shared::path::KeyPath;
use deckster_mode::{send_command, DecksterHandler};
use crate::config::{GlobalConfig, KeyConfig, KeyMode};
use crate::ha_client::{HaClient, StateUpdate};
pub struct Handler {
events_sender: broadcast::Sender<HandlerEvent>,
}
impl Handler {
pub fn new(data: InitialHandlerMessage<GlobalConfig, KeyConfig, ()>) -> Result<Self, HandlerInitializationError> {
let events_sender = broadcast::Sender::<HandlerEvent>::new(5);
let mut subscribed_entity_ids = Vec::new();
for c in data.key_configs.values() {
subscribed_entity_ids.push(c.mode.state_entity_id().clone())
}
thread::spawn({
let events_sender = events_sender.clone();
move || {
let runtime = tokio::runtime::Builder::new_current_thread().enable_time().enable_io().build().unwrap();
let task_set = LocalSet::new();
let ha_client = task_set.block_on(
&runtime,
HaClient::new(data.global_config.base_url, data.global_config.token, subscribed_entity_ids),
);
for (path, config) in data.key_configs {
task_set.spawn_local(manage_key(events_sender.subscribe(), ha_client.clone(), path, config));
}
runtime.block_on(task_set)
}
});
Ok(Handler { events_sender })
}
}
impl DecksterHandler for Handler {
fn handle(&mut self, event: HandlerEvent) {
// No receivers being available can be ignored.
_ = self.events_sender.send(event);
}
}
async fn manage_key(mut events: broadcast::Receiver<HandlerEvent>, ha_client: HaClient, path: KeyPath, config: KeyConfig) {
let state_entity_id = config.mode.state_entity_id();
if let Some(state) = &config.disconnected_state {
send_command(HandlerCommand::SetKeyStyle {
path: path.clone(),
value: config.style.get(state).cloned(),
})
}
let mut state_updates = ha_client.subscribe_to_state_updates();
loop {
select! {
Ok(update) = state_updates.recv() => {
match update {
StateUpdate::Disconnected => {
if let Some(state) = &config.disconnected_state {
send_command(HandlerCommand::SetKeyStyle {
path: path.clone(),
value: config.style.get(state).cloned()
})
}
}
StateUpdate::Actual(update) => {
if &update.entity_id == state_entity_id {
send_command(HandlerCommand::SetKeyStyle {
path: path.clone(),
value: config.style.get(&update.state).cloned()
})
}
}
}
}
Ok(HandlerEvent::Key { path: p, event }) = events.recv() => {
if p != path {
continue
}
if let KeyEvent::Press = event {
match &config.mode {
KeyMode::Toggle { entity_id } => {
ha_client.toggle_entity(entity_id).await;
}
KeyMode::Button { button_entity_id, .. } => {
ha_client.press_button_entity(button_entity_id).await;
}
}
}
}
}
}
}