From 864a6ccfe83c68f74437db3ac98ace9d7f93d978 Mon Sep 17 00:00:00 2001 From: Tess Ellenoir Duursma Date: Fri, 12 Jul 2024 03:46:06 +0200 Subject: [PATCH] Add support for remote config changes --- src/common.rs | 4 ++-- src/config.rs | 10 +++++++++ src/error.rs | 1 + src/main.rs | 9 +++------ src/mqtt.rs | 56 +++++++++++++++++++++++++++++---------------------- 5 files changed, 48 insertions(+), 32 deletions(-) diff --git a/src/common.rs b/src/common.rs index 2113462..8f96bad 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,6 +1,6 @@ -use serde::Deserialize; +use serde::{Deserialize, Serialize}; -#[derive(Debug, Deserialize)] +#[derive(Debug, Deserialize, Serialize)] pub struct Config { pub id: Option, pub host: String, diff --git a/src/config.rs b/src/config.rs index 25f4972..a8ce6d3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -21,4 +21,14 @@ impl Config { serde_json::from_reader(BufReader::new(file)).or(Err(Error::ParsingError)) } + + pub fn save(&self) -> Result<(), Error> { + let file = File::options() + .write(true) + .truncate(true) + .open("config.json") + .or(Err(Error::FileIoError))?; + + serde_json::to_writer(file, self).or(Err(Error::SerializationError)) + } } diff --git a/src/error.rs b/src/error.rs index 2b77382..14ca105 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,4 +3,5 @@ pub(crate) enum Error { NoConfigFileFound, FileIoError, ParsingError, + SerializationError, } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 502c4a4..07f61ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,20 +34,17 @@ fn main() -> wry::Result<()> { println!("The CPU serial number is {}", serial); - println!("Loading the config..."); - let config = Config::load(cli.default_config_path.map(|p| PathBuf::from(p))).unwrap(); + let default_config_path = cli.default_config_path.map(|p| PathBuf::from(p)); println!("Opening {}...", cli.url); let (sender, receiver) = channel(); let listener = mqtt::Listener { - id: config.id.unwrap_or(serial), - host: config.host, - port: config.port, + get_config: move || Config::load(default_config_path.clone()).unwrap(), sender, }; - listener.start().unwrap(); + listener.start(); browser::spawn_browser(cli.url, Some(receiver)) } diff --git a/src/mqtt.rs b/src/mqtt.rs index 333a94a..14f5a73 100644 --- a/src/mqtt.rs +++ b/src/mqtt.rs @@ -1,45 +1,53 @@ use std::{sync::mpsc::Sender, thread}; -use rumqttc::{Client, ClientError, MqttOptions, Packet, Publish}; +use rumqttc::{Client, MqttOptions, Packet, Publish}; -use crate::common::Command; +use crate::{ + common::{Command, Config}, + system::get_cpu_serial, +}; -pub(crate) struct Listener { - pub id: String, - pub host: String, - pub port: u16, +pub(crate) struct Listener Config + std::marker::Send> { + pub get_config: F, pub sender: Sender, } -impl Listener { - pub(crate) fn start(self) -> Result<(), ClientError> { - let (client, mut connection) = - Client::new(MqttOptions::new(&self.id, self.host, self.port), 64); +impl Config + std::marker::Send + 'static> Listener { + pub(crate) fn start(self) -> () { + thread::spawn(move || 'outer: loop { + let config = (self.get_config)(); + let id = config.id.unwrap_or(get_cpu_serial().unwrap()); + let (client, mut connection) = + Client::new(MqttOptions::new(&id, config.host, config.port), 64); - client.subscribe("screens", rumqttc::QoS::AtLeastOnce)?; - client.subscribe(format!("screens/{}", self.id), rumqttc::QoS::AtLeastOnce)?; + client + .subscribe("screens", rumqttc::QoS::AtLeastOnce) + .unwrap(); + client + .subscribe(format!("screens/{}", id), rumqttc::QoS::AtLeastOnce) + .unwrap(); + + let sender = self.sender.clone(); - thread::spawn(move || { for event in connection.iter() { println!("{:?}", event); - if let Ok(rumqttc::Event::Incoming(Packet::Publish(Publish { - topic, - payload, - .. - }))) = event + if let Ok(rumqttc::Event::Incoming(Packet::Publish(Publish { payload, .. }))) = + event { - if topic == "commands" { - if let Ok(command) = serde_json::from_slice::(&payload) { - println!("{:?}", command); + if let Ok(command) = serde_json::from_slice::(&payload) { + println!("{:?}", command); - self.sender.send(command).unwrap(); + if let Command::SetConfig(config) = command { + config.save().unwrap(); + client.disconnect().unwrap(); + continue 'outer; } + + sender.send(command).unwrap(); } } } }); - - Ok(()) } }