mod service_specific; mod shared; use std::{process::Command, time::Instant}; use anyhow::Result; use service_specific::*; use shared::config::{Config, COMMAND_COUNT, COMMAND_PAUSE}; fn main() -> Result<()> { // create serial port let mut port = Port::open(SerialPortSettings { baud_rate: 57600, data_bits: DataBits::Eight, parity: Parity::None, stop_bits: StopBits::One, flow_control: FlowControl::None, timeout: Duration::from_millis(2500), })?; let mut message_builder = MessageBuilder::default(); let mut button_infos = [Duration::default(); COMMAND_COUNT]; let start_time = Instant::now(); // loop forever loop { // check if port could be read if let Ok(r) = port.read() { // handle incoming message match r { SerialReadResult::Message(msg) => { // create message out of stream // discard remaining for now if let Some(_remaining) = message_builder.check(msg) { debug_assert!(message_builder.is_complete()); println!("{}", message_builder.message()); // if message can be parsed to a number, try to execute a command if let Ok(index) = message_builder.message().parse() { execute_button_press(index, start_time.elapsed(), &mut button_infos)?; } message_builder = MessageBuilder::default(); } } SerialReadResult::Timeout => (), } } } } fn execute_button_press( button_id: usize, time: Duration, button_infos: &mut [Duration; COMMAND_COUNT], ) -> Result<()> { // load config every button // since it could be modified from the gui application let config = Config::load_config()?; // check if ID is in a valid range if button_id < 1 && button_id > COMMAND_COUNT { return Ok(()); } // check that this commands last execution is longer than COMMAND_PAUSE ago if (button_infos[button_id] + COMMAND_PAUSE) < time { button_infos[button_id] = time; } else { return Ok(()); } // check command at ID position if a command is set // if so, simply execute this command as child process if let Some(cmd) = &config.commands[button_id - 1] { if !cmd.is_empty() { println!("cmd: {}", cmd); Command::new(cmd).spawn()?; } } Ok(()) }