126 lines
4.7 KiB
Rust
126 lines
4.7 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use common::{BulbPrefs, ClientMessage, ScriptId, ServerMessage};
|
|
use lighter_lib::BulbId;
|
|
use lighter_manager::manager::{BulbCommand, BulbManager, BulbSelector};
|
|
use lighter_manager::provider::mqtt::BulbsMqtt;
|
|
use serde::{Deserialize, Serialize};
|
|
use tokio::select;
|
|
|
|
use crate::persistence::PersistenceFile;
|
|
use crate::State;
|
|
|
|
use self::scripts::{LightScript, Party, Waker};
|
|
|
|
pub mod scripts;
|
|
|
|
#[derive(Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
struct LightsState {
|
|
script_prefs: HashMap<ScriptId, HashMap<BulbId, BulbPrefs>>,
|
|
}
|
|
|
|
pub async fn lights_task(state: &State) {
|
|
let config = &state.config;
|
|
let server_message = &state.server_message;
|
|
let mut client_message = state.client_message.subscribe();
|
|
let mut lights_state: PersistenceFile<LightsState> = state
|
|
.persistence
|
|
.open("lights".into())
|
|
.await
|
|
.expect("Failed to open lights config");
|
|
|
|
let provider = BulbsMqtt::new(config.bulbs.clone(), config.mqtt.clone());
|
|
let manager = BulbManager::launch(config.bulbs.clone(), provider)
|
|
.await
|
|
.expect("Failed to launch bulb manager");
|
|
|
|
let mut scripts: HashMap<ScriptId, Box<dyn LightScript + Send>> = Default::default();
|
|
scripts.insert(
|
|
"waker".to_string(),
|
|
Box::new(Waker::create(manager.clone())),
|
|
);
|
|
scripts.insert(
|
|
"party".to_string(),
|
|
Box::new(Party::create(manager.clone())),
|
|
);
|
|
|
|
for (script, prefs) in &lights_state.get().script_prefs {
|
|
let Some(script) = scripts.get_mut(script) else {
|
|
continue;
|
|
};
|
|
|
|
for (bulb, prefs) in prefs {
|
|
for (name, value) in &prefs.kvs {
|
|
script.set_param(bulb, name, value.clone())
|
|
}
|
|
}
|
|
}
|
|
|
|
loop {
|
|
select! {
|
|
_ = manager.notify_on_change() => {
|
|
for (id, mode) in manager.bulbs().await.clone().into_iter() {
|
|
let prefs = scripts.iter_mut()
|
|
.map(|(script, prefs)|
|
|
(script.clone(), prefs.get_params(&id)))
|
|
.collect();
|
|
|
|
let msg = ServerMessage::BulbState { id, mode, prefs };
|
|
if let Err(e) = server_message.send(msg) {
|
|
error!("broadcast channel error: {e}");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
request = client_message.recv() => {
|
|
let request = match request {
|
|
Ok(r) => r,
|
|
Err(_) => continue,
|
|
};
|
|
|
|
match request.message {
|
|
ClientMessage::SetBulbColor { id, color } => {
|
|
manager.send_command(BulbCommand::SetColor(BulbSelector::Id(id), color)).await;
|
|
}
|
|
ClientMessage::SetBulbPower { id, power } => {
|
|
manager.send_command(BulbCommand::SetPower(BulbSelector::Id(id), power)).await;
|
|
}
|
|
ClientMessage::GetBulbs => {
|
|
if let Err(e) = request.response.send(ServerMessage::BulbMap(config.bulb_map.clone())).await {
|
|
error!("GetBulbs response channel error: {e}");
|
|
return;
|
|
}
|
|
for (id, mode) in manager.bulbs().await.clone().into_iter() {
|
|
let prefs = scripts.iter_mut()
|
|
.map(|(script, prefs)|
|
|
(script.clone(), prefs.get_params(&id)))
|
|
.collect();
|
|
|
|
let msg = ServerMessage::BulbState { id, mode, prefs };
|
|
if let Err(e) = request.response.send(msg).await {
|
|
error!("GetBulbs response channel error: {e}");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
ClientMessage::SetBulbPref { bulb, script, name, value } => {
|
|
let Some(s) = scripts.get_mut(&script) else {
|
|
continue;
|
|
};
|
|
s.set_param(&bulb, &name, value.clone());
|
|
|
|
// TODO handle error
|
|
lights_state.update(move |state| {
|
|
state.script_prefs
|
|
.entry(script).or_default()
|
|
.entry(bulb).or_default()
|
|
.kvs.insert(name, value);
|
|
}).await.expect("failed to persist lights state");
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|