diff --git a/crates/deckster_shared/src/handler_communication.rs b/crates/deckster_shared/src/handler_communication.rs index 1f1f1cc..e8f267f 100644 --- a/crates/deckster_shared/src/handler_communication.rs +++ b/crates/deckster_shared/src/handler_communication.rs @@ -50,7 +50,6 @@ pub enum HandlerEvent { #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] #[serde(tag = "command", rename_all = "kebab-case")] pub enum HandlerCommand { - SetActivePages { key_page_id: String, knob_page_id: String }, SetKeyStyle { path: KeyPath, value: Option }, SetKnobStyle { path: KnobPath, value: Option }, SetKnobValue { path: KnobPath, value: Option }, diff --git a/crates/deckster_shared/src/state.rs b/crates/deckster_shared/src/state.rs index b60aee1..8356f31 100644 --- a/crates/deckster_shared/src/state.rs +++ b/crates/deckster_shared/src/state.rs @@ -6,6 +6,7 @@ use crate::style::{KeyStyle, KnobStyle}; #[derive(Debug)] pub struct Key { pub path: KeyPath, + pub host_id: Box, pub base_style: KeyStyle, pub style: Option, } @@ -13,6 +14,7 @@ pub struct Key { #[derive(Debug)] pub struct Knob { pub path: KnobPath, + pub host_id: Box, pub base_style: KnobStyle, pub style: Option, pub value: Option, diff --git a/src/coordinator/graphics.rs b/src/coordinator/graphics.rs index f890d58..6cfb6a0 100644 --- a/src/coordinator/graphics.rs +++ b/src/coordinator/graphics.rs @@ -1,4 +1,5 @@ use std::cell::RefCell; +use std::collections::HashSet; use bytes::{BufMut, Bytes, BytesMut}; use resvg::usvg::tiny_skia_path::PathBuilder; @@ -18,100 +19,105 @@ pub struct GraphicsContext { pub icon_manager: IconManager, } -pub fn render_key(context: &GraphicsContext, key_size: IntSize, state: Option<&Key>) -> Bytes { +pub fn render_key(context: &GraphicsContext, key_size: IntSize, active_remote_handler_host_ids: &HashSet>, state: Option<&Key>) -> Bytes { let mut pixmap = Pixmap::new(key_size.width(), key_size.height()).expect("constraints were already asserted by IntSize"); if let Some(state) = state { - let style = state.style.as_ref().map(|s| s.merge_over(&state.base_style)); - let style = style.as_ref().unwrap_or(&state.base_style); + if active_remote_handler_host_ids.contains(&state.host_id) { + let style = state.style.as_ref().map(|s| s.merge_over(&state.base_style)); + let style = style.as_ref().unwrap_or(&state.base_style); - if let Some(icon) = &style.icon { - if let Err(e) = context.icon_manager.render_icon_in(&mut pixmap, icon) { - log::error!("Failed to render key: {}", e); + if let Some(icon) = &style.icon { + if let Err(e) = context.icon_manager.render_icon_in(&mut pixmap, icon) { + log::error!("Failed to render key: {}", e); + } } - } - if let Some(label) = &style.label { - if !label.is_empty() { - context.label_renderer.borrow_mut().render(&mut pixmap, label); + if let Some(label) = &style.label { + if !label.is_empty() { + context.label_renderer.borrow_mut().render(&mut pixmap, label); + } } - } - if let Some(color) = style.border { - let path = - PathBuilder::from_rect(Rect::from_xywh(-1.0, -2.0, pixmap.width() as f32, pixmap.height() as f32).expect("width and height are not negative")); + if let Some(color) = style.border { + let path = PathBuilder::from_rect( + Rect::from_xywh(-1.0, -2.0, pixmap.width() as f32, pixmap.height() as f32).expect("width and height are not negative"), + ); - let paint = Paint { - shader: Shader::SolidColor(Color::from_rgba8(color.r, color.g, color.b, color.a)), - ..Paint::default() - }; + let paint = Paint { + shader: Shader::SolidColor(Color::from_rgba8(color.r, color.g, color.b, color.a)), + ..Paint::default() + }; - static STROKE: Stroke = Stroke { - width: 15.0, - miter_limit: 4.0, - line_cap: LineCap::Butt, - line_join: LineJoin::Round, - dash: None, - }; + static STROKE: Stroke = Stroke { + width: 15.0, + miter_limit: 4.0, + line_cap: LineCap::Butt, + line_join: LineJoin::Round, + dash: None, + }; - pixmap.stroke_path(&path, &paint, &STROKE, Transform::identity(), None); + pixmap.stroke_path(&path, &paint, &STROKE, Transform::identity(), None); + } } } convert_pixels_to_rgb565(pixmap.pixels(), context.buffer_endianness).freeze() } -pub fn render_knob(context: &GraphicsContext, screen_size: IntSize, state: Option<&Knob>) -> Bytes { +pub fn render_knob(context: &GraphicsContext, screen_size: IntSize, active_remote_handler_host_ids: &HashSet>, state: Option<&Knob>) -> Bytes { let mut pixmap = Pixmap::new(screen_size.width(), screen_size.height()).expect("constraints were already asserted by IntSize"); if let Some(state) = state { - let style = state.style.as_ref().map(|s| s.merge_over(&state.base_style)); - let style = style.as_ref().unwrap_or(&state.base_style); + if active_remote_handler_host_ids.contains(&state.host_id) { + let style = state.style.as_ref().map(|s| s.merge_over(&state.base_style)); + let style = style.as_ref().unwrap_or(&state.base_style); - if let Some(icon) = &style.icon { - if let Err(e) = context.icon_manager.render_icon_in(&mut pixmap, icon) { - log::error!("Failed to render knob: {}", e); + if let Some(icon) = &style.icon { + if let Err(e) = context.icon_manager.render_icon_in(&mut pixmap, icon) { + log::error!("Failed to render knob: {}", e); + } } - } - if let Some(label) = &style.label { - if !label.is_empty() { - context.label_renderer.borrow_mut().render(&mut pixmap, label); + if let Some(label) = &style.label { + if !label.is_empty() { + context.label_renderer.borrow_mut().render(&mut pixmap, label); + } } - } - if let Some(indicators) = &style.indicators { - if let Some(bar) = indicators.bar.as_ref() { - let color = bar.color.unwrap_or(RGBA::new(0xff, 0xff, 0xff, 0x50).into()); - const WIDTH: f32 = 5.0; - const PADDING_X: f32 = 5.0; - const PADDING_Y: f32 = 20.0; - const HEIGHT_AT_ZERO: f32 = 2.0; + if let Some(indicators) = &style.indicators { + if let Some(bar) = indicators.bar.as_ref() { + let color = bar.color.unwrap_or(RGBA::new(0xff, 0xff, 0xff, 0x50).into()); + const WIDTH: f32 = 5.0; + const PADDING_X: f32 = 5.0; + const PADDING_Y: f32 = 20.0; + const HEIGHT_AT_ZERO: f32 = 2.0; - let max_height: f32 = pixmap.height() as f32 - PADDING_Y * 2.0; - let height = if let Some(value) = &state.value { - HEIGHT_AT_ZERO + value * (max_height - HEIGHT_AT_ZERO) - } else { - 0.0 - }; + let max_height: f32 = pixmap.height() as f32 - PADDING_Y * 2.0; + let height = if let Some(value) = &state.value { + HEIGHT_AT_ZERO + value * (max_height - HEIGHT_AT_ZERO) + } else { + 0.0 + }; - let x = if state.path.position.is_left() { - PADDING_X - } else { - pixmap.width() as f32 - PADDING_X - WIDTH - }; + let x = if state.path.position.is_left() { + PADDING_X + } else { + pixmap.width() as f32 - PADDING_X - WIDTH + }; - let y = pixmap.height() as f32 - PADDING_Y - height; + let y = pixmap.height() as f32 - PADDING_Y - height; - pixmap.fill_rect( - Rect::from_xywh(x, y, WIDTH, height).expect("WIDTH and height are not negative"), - &Paint { - shader: Shader::SolidColor(Color::from_rgba8(color.r, color.g, color.b, color.a)), - ..Paint::default() - }, - Transform::identity(), - None, - ); + pixmap.fill_rect( + Rect::from_xywh(x, y, WIDTH, height).expect("WIDTH and height are not negative"), + &Paint { + shader: Shader::SolidColor(Color::from_rgba8(color.r, color.g, color.b, color.a)), + ..Paint::default() + }, + Transform::identity(), + None, + ); + } } } } diff --git a/src/coordinator/io_worker.rs b/src/coordinator/io_worker.rs index be7e7f1..95ca760 100644 --- a/src/coordinator/io_worker.rs +++ b/src/coordinator/io_worker.rs @@ -21,17 +21,25 @@ use crate::icons::IconManager; use crate::model::coordinator_config::Config; use crate::model::position::ButtonPosition; +#[derive(Debug, PartialEq, Clone)] +pub enum CoordinatorCommand { + SetActivePages { key_page_id: String, knob_page_id: String }, + SetRemoteHostIsActive { host_id: Box, is_active: bool }, +} + enum IoWork { DeviceEvent(LoupedeckEvent), - Command(HandlerCommand), + HandlerCommand(HandlerCommand), + CoordinatorCommand(CoordinatorCommand), } pub struct IoWorkerContext { config: Arc, device: LoupedeckDevice, - commands_sender: flume::Sender, + coordinator_commands_sender: flume::Sender, events_sender: broadcast::Sender, graphics: GraphicsContext, + state: State, } impl IoWorkerContext { @@ -39,52 +47,59 @@ impl IoWorkerContext { config_directory: &Path, config: Arc, device: LoupedeckDevice, - commands_sender: flume::Sender, + coordinator_commands_sender: flume::Sender, events_sender: broadcast::Sender, ) -> Self { let buffer_endianness = device.characteristics().key_grid.display.endianness; let label_renderer = RefCell::new(LabelRenderer::new(config.label_font_family.as_ref())); let dpi = device.characteristics().key_grid.display.dpi; let icon_packs = Arc::clone(&config.icon_packs); + let state = State::create(&config); IoWorkerContext { config, device, - commands_sender, + coordinator_commands_sender, events_sender, graphics: GraphicsContext { buffer_endianness, label_renderer, icon_manager: IconManager::new(config_directory.to_path_buf(), icon_packs, dpi), }, + state, } } } -pub fn do_io_work(context: IoWorkerContext, commands_receiver: flume::Receiver) { - let mut state = State::create(&context.config); +pub fn do_io_work( + mut context: IoWorkerContext, + coordinator_commands_receiver: &flume::Receiver, + handler_commands_receiver: &flume::Receiver, +) { let device_events_receiver = context.device.events(); loop { - let a = flume::Selector::new() + let work = flume::Selector::new() .recv(&device_events_receiver, |e| { IoWork::DeviceEvent(e.expect("the device events channel is not closed by the other side")) }) - .recv(&commands_receiver, |c| IoWork::Command(c.unwrap())) + .recv(coordinator_commands_receiver, |c| IoWork::CoordinatorCommand(c.unwrap())) + .recv(handler_commands_receiver, |c| IoWork::HandlerCommand(c.unwrap())) .wait(); - match a { + match work { IoWork::DeviceEvent(event) => { - if !handle_event(&context, &mut state, event) { + if !handle_event(&mut context, event) { break; } } - IoWork::Command(command) => handle_command(&context, &mut state, command), + IoWork::CoordinatorCommand(command) => handle_coordinator_command(&mut context, command), + IoWork::HandlerCommand(command) => handle_handler_command(&mut context, command), } } } -fn handle_event(context: &IoWorkerContext, state: &mut State, event: LoupedeckEvent) -> bool { +fn handle_event(context: &mut IoWorkerContext, event: LoupedeckEvent) -> bool { log::trace!("Handling event: {:?}", &event); let send_key_event = |path: KeyPath, event: KeyEvent| { @@ -104,10 +119,10 @@ fn handle_event(context: &IoWorkerContext, state: &mut State, event: LoupedeckEv let button_config = &context.config.buttons[position]; context - .commands_sender - .send(HandlerCommand::SetActivePages { - key_page_id: button_config.key_page.as_ref().unwrap_or(&state.active_key_page_id).clone(), - knob_page_id: button_config.knob_page.as_ref().unwrap_or(&state.active_knob_page_id).clone(), + .coordinator_commands_sender + .send(CoordinatorCommand::SetActivePages { + key_page_id: button_config.key_page.as_ref().unwrap_or(&context.state.active_key_page_id).clone(), + knob_page_id: button_config.knob_page.as_ref().unwrap_or(&context.state.active_knob_page_id).clone(), }) .unwrap() } @@ -125,7 +140,7 @@ fn handle_event(context: &IoWorkerContext, state: &mut State, event: LoupedeckEv }; let path = KeyPath { - page_id: state.active_key_page_id.clone(), + page_id: context.state.active_key_page_id.clone(), position, }; @@ -137,10 +152,10 @@ fn handle_event(context: &IoWorkerContext, state: &mut State, event: LoupedeckEv .expect("the key index is valid because is was returned by get_key_at_global_coordinates"); let kind = if is_end { - state.active_touch_ids.remove(&touch_id); + context.state.active_touch_ids.remove(&touch_id); KeyTouchEventKind::End } else { - let is_new = state.active_touch_ids.insert(touch_id); + let is_new = context.state.active_touch_ids.insert(touch_id); if is_new { KeyTouchEventKind::Start } else { @@ -170,7 +185,7 @@ fn handle_event(context: &IoWorkerContext, state: &mut State, event: LoupedeckEv send_knob_event( KnobPath { - page_id: state.active_knob_page_id.clone(), + page_id: context.state.active_knob_page_id.clone(), position, }, KnobEvent::Rotate { @@ -186,7 +201,7 @@ fn handle_event(context: &IoWorkerContext, state: &mut State, event: LoupedeckEv send_knob_event( KnobPath { - page_id: state.active_knob_page_id.clone(), + page_id: context.state.active_knob_page_id.clone(), position, }, KnobEvent::Press, @@ -198,46 +213,53 @@ fn handle_event(context: &IoWorkerContext, state: &mut State, event: LoupedeckEv true } -fn handle_command(context: &IoWorkerContext, state: &mut State, command: HandlerCommand) { - log::trace!("Handling command: {:?}", &command); +fn handle_coordinator_command(context: &mut IoWorkerContext, command: CoordinatorCommand) { + log::trace!("Handling coordinator command: {:?}", &command); match command { - HandlerCommand::SetActivePages { key_page_id, knob_page_id } => { - state.active_key_page_id = key_page_id; - state.active_knob_page_id = knob_page_id; + CoordinatorCommand::SetActivePages { key_page_id, knob_page_id } => { + context.state.active_key_page_id = key_page_id; + context.state.active_knob_page_id = knob_page_id; for button in context.device.characteristics().available_buttons { context .device - .set_button_color(button, get_correct_button_color(context, state, ButtonPosition::of(&button))) + .set_button_color(button, get_correct_button_color(context, &context.state, ButtonPosition::of(&button))) .expect("the button is available for this device because that is literally what we are iterating over"); } - let key_grid = &context.device.characteristics().key_grid; - for index in 0..(key_grid.rows * key_grid.columns) { - draw_key_at_index(context, state, index); - } - - for position in KnobPosition::VARIANTS { - draw_knob_at_position(context, state, *position); - } - - context.device.refresh_display(&key_grid.display).unwrap(); + redraw_visible_page(&context); } + CoordinatorCommand::SetRemoteHostIsActive { host_id, is_active } => { + if is_active { + context.state.active_remote_handler_host_ids.insert(host_id); + } else { + context.state.active_remote_handler_host_ids.remove(&host_id); + } + + redraw_visible_page(&context); + } + } +} + +fn handle_handler_command(context: &mut IoWorkerContext, command: HandlerCommand) { + log::trace!("Handling handler command: {:?}", &command); + + match command { HandlerCommand::SetKeyStyle { path, value } => { - state.mutate_key_for_command("SetKeyStyle", &path, |k| { + context.state.mutate_key_for_command("SetKeyStyle", &path, |k| { k.style = value; }); - draw_key_at_path_if_visible(context, state, path); + draw_key_at_path_if_visible(context, path); context.device.refresh_display(&context.device.characteristics().key_grid.display).unwrap(); } HandlerCommand::SetKnobStyle { path, value } => { - state.mutate_knob_for_command("SetKnobStyle", &path, |k| { + context.state.mutate_knob_for_command("SetKnobStyle", &path, |k| { k.style = value; }); - draw_knob_at_path_if_visible(context, state, path); + draw_knob_at_path_if_visible(context, path); context.device.refresh_display(&context.device.characteristics().key_grid.display).unwrap(); } HandlerCommand::SetKnobValue { path, value } => { @@ -248,15 +270,28 @@ fn handle_command(context: &IoWorkerContext, state: &mut State, command: Handler } } - state.mutate_knob_for_command("SetKnobValue", &path, |k| { + context.state.mutate_knob_for_command("SetKnobValue", &path, |k| { k.value = value; }); - draw_knob_at_path_if_visible(context, state, path); + draw_knob_at_path_if_visible(context, path); } } } +fn redraw_visible_page(context: &IoWorkerContext) { + let key_grid = &context.device.characteristics().key_grid; + for index in 0..(key_grid.rows * key_grid.columns) { + draw_key_at_index(context, index); + } + + for position in KnobPosition::VARIANTS { + draw_knob_at_position(context, *position); + } + + context.device.refresh_display(&key_grid.display).unwrap(); +} + // active -> config.active_button_color // no actions defined -> #000000 // inactive -> config.inactive_button_color @@ -306,6 +341,7 @@ fn draw_key(context: &IoWorkerContext, index: u8, key: Option<&Key>) { let buffer = render_key( &context.graphics, IntSize::from_wh(rect.w as u32, rect.h as u32).expect("rect.w and rect.h are not zero"), + &context.state.active_remote_handler_host_ids, key, ); context @@ -314,23 +350,23 @@ fn draw_key(context: &IoWorkerContext, index: u8, key: Option<&Key>) { .unwrap(); } -fn draw_key_at_index(context: &IoWorkerContext, state: &State, index: u8) { +fn draw_key_at_index(context: &IoWorkerContext, index: u8) { let position = get_key_position_for_index(&context.device.characteristics().key_grid, index); - draw_key(context, index, state.active_key_page().keys_by_position.get(&position)); + draw_key(context, index, context.state.active_key_page().keys_by_position.get(&position)); } -fn draw_key_at_position_if_visible(context: &IoWorkerContext, state: &State, position: KeyPosition) { +fn draw_key_at_position_if_visible(context: &IoWorkerContext, position: KeyPosition) { let index = get_key_index_for_position(&context.device.characteristics().key_grid, position); if let Some(index) = index { - draw_key(context, index, state.active_key_page().keys_by_position.get(&position)); + draw_key(context, index, context.state.active_key_page().keys_by_position.get(&position)); } } -fn draw_key_at_path_if_visible(context: &IoWorkerContext, state: &State, path: KeyPath) { - if state.active_key_page_id == path.page_id { - draw_key_at_position_if_visible(context, state, path.position); +fn draw_key_at_path_if_visible(context: &IoWorkerContext, path: KeyPath) { + if context.state.active_key_page_id == path.page_id { + draw_key_at_position_if_visible(context, path.position); } } @@ -346,6 +382,7 @@ fn draw_knob(context: &IoWorkerContext, position: KnobPosition, knob: Option<&Kn let buffer = render_knob( &context.graphics, IntSize::from_wh(rect.w as u32, rect.h as u32).expect("rect.w and rect.h are not zero."), + &context.state.active_remote_handler_host_ids, knob, ); context @@ -355,13 +392,13 @@ fn draw_knob(context: &IoWorkerContext, position: KnobPosition, knob: Option<&Kn } } -fn draw_knob_at_position(context: &IoWorkerContext, state: &State, position: KnobPosition) { - draw_knob(context, position, Some(&state.active_knob_page().knobs_by_position[position])); +fn draw_knob_at_position(context: &IoWorkerContext, position: KnobPosition) { + draw_knob(context, position, Some(&context.state.active_knob_page().knobs_by_position[position])); } -fn draw_knob_at_path_if_visible(context: &IoWorkerContext, state: &State, path: KnobPath) { - if state.active_knob_page_id == path.page_id { - draw_knob_at_position(context, state, path.position); +fn draw_knob_at_path_if_visible(context: &IoWorkerContext, path: KnobPath) { + if context.state.active_knob_page_id == path.page_id { + draw_knob_at_position(context, path.position); } } diff --git a/src/coordinator/mod.rs b/src/coordinator/mod.rs index 579cddc..147b2e4 100644 --- a/src/coordinator/mod.rs +++ b/src/coordinator/mod.rs @@ -12,12 +12,11 @@ use deckster_shared::path::{KeyPath, KnobPath}; use loupedeck_serial::commands::VibrationPattern; use loupedeck_serial::device::LoupedeckDevice; -use crate::coordinator::io_worker::{do_io_work, IoWorkerContext}; +use crate::coordinator::io_worker::{do_io_work, CoordinatorCommand, IoWorkerContext}; use crate::coordinator::mqtt::start_mqtt_client; use crate::handler_runner; use crate::handler_runner::KeyOrKnobHandlerConfig; use crate::model::coordinator_config::Config; -use crate::model::get_default_host_id; use crate::model::mqtt::HandlerHostsConfig; mod graphics; @@ -33,11 +32,12 @@ pub async fn start(config_directory: &Path, config: Config) -> Result<()> { let available_device = available_devices.first().wrap_err("No device connected.")?; log::info!("Found {} device(s).", available_devices.len()); - let (commands_sender, commands_receiver) = flume::bounded::(5); + let (coordinator_commands_sender, coordinator_commands_receiver) = flume::bounded::(5); + let (handler_commands_sender, handler_commands_receiver) = flume::bounded::(5); let events_sender = broadcast::Sender::::new(5); - commands_sender - .send(HandlerCommand::SetActivePages { + coordinator_commands_sender + .send(CoordinatorCommand::SetActivePages { knob_page_id: config.initial.knob_page.clone(), key_page_id: config.initial.key_page.clone(), }) @@ -91,16 +91,16 @@ pub async fn start(config_directory: &Path, config: Config) -> Result<()> { if let Some(mqtt_config) = &config.mqtt { log::info!("Initializing MQTT client…"); - start_mqtt_client(mqtt_config, &handler_hosts_config, commands_sender.clone(), events_sender.subscribe()).await; + start_mqtt_client(mqtt_config, &handler_hosts_config, handler_commands_sender.clone(), events_sender.subscribe()).await; } log::info!("Initializing handler processes…"); handler_runner::start( - get_default_host_id(), + String::default().into_boxed_str(), &config_directory.join("handlers"), handler_hosts_config, - commands_sender.clone(), + handler_commands_sender.clone(), events_sender.subscribe(), ) .await?; @@ -112,12 +112,12 @@ pub async fn start(config_directory: &Path, config: Config) -> Result<()> { device.set_brightness(0.5); device.vibrate(VibrationPattern::RiseFall); - let io_worker_context = IoWorkerContext::create(config_directory, Arc::clone(&config), device, commands_sender.clone(), events_sender); + let io_worker_context = IoWorkerContext::create(config_directory, Arc::clone(&config), device, coordinator_commands_sender, events_sender); let io_worker_thread = thread::Builder::new() .name("deckster IO worker".to_owned()) .spawn(move || { - do_io_work(io_worker_context, commands_receiver); + do_io_work(io_worker_context, &coordinator_commands_receiver, &handler_commands_receiver); }) .wrap_err("Could not spawn the worker thread")?; diff --git a/src/coordinator/state.rs b/src/coordinator/state.rs index 1e70ec5..b925c6d 100644 --- a/src/coordinator/state.rs +++ b/src/coordinator/state.rs @@ -13,6 +13,7 @@ pub struct State { pub active_key_page_id: String, pub active_knob_page_id: String, pub active_touch_ids: HashSet, + pub active_remote_handler_host_ids: HashSet>, pub key_pages_by_id: HashMap, pub knob_pages_by_id: HashMap, } @@ -32,6 +33,7 @@ impl State { page_id: p.id.clone(), position: *position, }, + host_id: k.host.clone(), base_style: k.base_style.clone(), style: None, }) @@ -54,6 +56,7 @@ impl State { page_id: p.id.clone(), position, }, + host_id: knob_config.host.clone(), base_style: knob_config.base_style.clone(), style: None, value: None, @@ -67,6 +70,7 @@ impl State { active_key_page_id: config.initial.key_page.clone(), active_knob_page_id: config.initial.knob_page.clone(), active_touch_ids: HashSet::new(), + active_remote_handler_host_ids: HashSet::new(), key_pages_by_id, knob_pages_by_id, } diff --git a/src/handler_host/mqtt.rs b/src/handler_host/mqtt.rs index 269d3bb..5f1a47e 100644 --- a/src/handler_host/mqtt.rs +++ b/src/handler_host/mqtt.rs @@ -135,7 +135,6 @@ pub async fn start_mqtt_client( tokio::spawn(async move { while let Ok(command) = commands_receiver.recv_async().await { match command { - HandlerCommand::SetActivePages { .. } => log::warn!("HandlerCommand::SetActivePages is not supported for remote handlers."), HandlerCommand::SetKeyStyle { path, value } => client .publish( format!("{topic_prefix}/keys/{path}/style"), diff --git a/src/model/key_page.rs b/src/model/key_page.rs index c50afc5..24c00e0 100644 --- a/src/model/key_page.rs +++ b/src/model/key_page.rs @@ -50,7 +50,7 @@ pub struct Key { #[serde(default, flatten)] pub base_style: KeyStyle, - #[serde(default = "super::get_default_host_id")] + #[serde(default)] pub host: Box, pub handler: Box, pub config: Arc, diff --git a/src/model/knob_page.rs b/src/model/knob_page.rs index ed385d3..724f6bf 100644 --- a/src/model/knob_page.rs +++ b/src/model/knob_page.rs @@ -24,7 +24,7 @@ pub struct Knob { #[serde(default, flatten)] pub base_style: KnobStyle, - #[serde(default = "super::get_default_host_id")] + #[serde(default)] pub host: Box, pub handler: Box, pub config: Arc, diff --git a/src/model/mod.rs b/src/model/mod.rs index 72e2b1c..515978a 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -5,7 +5,3 @@ pub mod key_page; pub mod knob_page; pub mod mqtt; pub mod position; - -pub fn get_default_host_id() -> Box { - "local".to_owned().into_boxed_str() -}