task: rewrite event handling as a step towards event-based subscriptions

This commit is contained in:
2024-12-14 14:53:24 +01:00
parent f9a8b32d3e
commit a0d524b825
8 changed files with 319 additions and 158 deletions

111
src/scenes.rs Normal file
View File

@@ -0,0 +1,111 @@
use std::str::FromStr;
use crate::task::Task;
use crate::events::*;
#[derive(Debug, PartialEq, Eq, Clone)]
struct Scene {
name: &'static str,
patterns: Vec<&'static str>,
trigger: Trigger
}
#[derive(Debug, PartialEq, Eq, Clone)]
enum Trigger {
Startup,
PropertyEquals(&'static str, Variant)
}
pub struct Sequencer {
scenes: Vec<Scene>,
cur_scene: String
}
impl Sequencer {
pub fn new() -> Self {
Sequencer {
cur_scene: String::new(),
scenes: vec![
Scene {
name: "Start",
patterns: vec!["Idle"],
trigger: Trigger::Startup
},
Scene {
name: "Online",
patterns: vec!["Idle"],
trigger: Trigger::PropertyEquals("system.network.online", Variant::Boolean(true))
}
]
}
}
fn get_scene(&self, name: &String) -> Option<&Scene> {
for scene in self.scenes.iter() {
if scene.name == name {
return Some(scene);
}
}
return None;
}
fn apply_scene(&mut self, name: &String, bus: &mut EventBus) {
if let Some(dst_tasks) = self.get_scene(name) {
if let Some(src_tasks) = self.get_scene(&self.cur_scene) {
let stop_queue = src_tasks.patterns.iter().filter(|i| !dst_tasks.patterns.contains(i));
let start_queue = dst_tasks.patterns.iter().filter(|i| !src_tasks.patterns.contains(i));
log::info!("Switching scene from {} to {}", self.cur_scene, name);
for stop in stop_queue {
bus.push(Event::new_stop_thing(stop));
}
for start in start_queue {
bus.push(Event::new_start_thing(start));
}
} else {
log::info!("Starting new scene {}", name);
log::info!("start={:?}", dst_tasks.patterns);
for start in dst_tasks.patterns.iter() {
bus.push(Event::new_start_thing(start));
}
}
self.cur_scene = name.clone();
} else {
panic!("Could not apply scene {:?} scenes={:?}", name, self.scenes);
}
}
}
impl Task for Sequencer {
fn start(&mut self, bus: &mut EventBus) {
log::info!("Starting sequencer!!!");
let startup_scene = self.scenes.iter().filter(|i| { i.trigger == Trigger::Startup }).next().unwrap();
bus.push(Event::new_property_change("scenes.current", startup_scene.name));
}
fn on_property_change(&mut self, key: &'static str, value: &Variant, bus: &mut EventBus) {
match (key, value) {
("scenes.current", Variant::String(scene_name)) => {
log::info!("Applying scene");
self.apply_scene(scene_name, bus);
},
(key, value) => {
for scene in self.scenes.iter() {
match scene.trigger {
Trigger::PropertyEquals(trigger_key, ref trigger_value) => {
if trigger_key == key && trigger_value == value {
log::info!("Triggering scene {}", scene.name);
bus.push(Event::new_property_change("scenes.current", scene.name))
}
},
_ => ()
}
}
}
_ => ()
}
}
}