use std::time::Duration;
use serial_core::prelude::*;
use thiserror::Error;
use flipdot_core::{Frame, Message, SignBus};
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum OdkError {
#[error("Sign bus failed to process message")]
Bus {
#[from]
source: Box<dyn std::error::Error + Send + Sync>,
},
#[error("ODK communication error")]
Communication {
#[from]
source: flipdot_core::FrameError,
},
}
#[derive(Debug, PartialEq, Eq, Hash)]
pub struct Odk<P: SerialPort, B: SignBus> {
port: P,
bus: B,
}
impl<P: SerialPort, B: SignBus> Odk<P, B> {
pub fn try_new(mut port: P, bus: B) -> Result<Self, serial_core::Error> {
flipdot_serial::configure_port(&mut port, Duration::from_secs(10))?;
Ok(Odk { port, bus })
}
pub fn process_message(&mut self) -> Result<(), OdkError> {
let response = {
let frame = Frame::read(&mut self.port)?;
let message = Message::from(frame);
self.bus.process_message(message)?
};
if let Some(message) = response {
let frame = Frame::from(message);
frame.write(&mut self.port)?;
}
Ok(())
}
}