use postcard_rpc::{ header::VarSeqKind, host_client::{HostClient, HostErr}, standard_icd::{PingEndpoint, WireError, ERROR_PATH}, }; use std::convert::Infallible; use bioz_icd::{ AccelRange, BadPositionError, GetUniqueIdEndpoint, Rgb8, SetAllLedEndpoint, SetSingleLedEndpoint, SingleLed, StartAccel, StartAccelerationEndpoint, StopAccelerationEndpoint, }; #[derive(Debug)] pub struct WorkbookClient { pub client: HostClient, } #[derive(Debug)] pub enum WorkbookError { Comms(HostErr), Endpoint(E), } impl From> for WorkbookError { fn from(value: HostErr) -> Self { Self::Comms(value) } } trait FlattenErr { type Good; type Bad; fn flatten(self) -> Result>; } impl FlattenErr for Result { type Good = T; type Bad = E; fn flatten(self) -> Result> { self.map_err(WorkbookError::Endpoint) } } // --- impl WorkbookClient { pub fn new() -> Self { let client = HostClient::new_raw_nusb( |d| d.product_string() == Some("bioz-amplifier"), ERROR_PATH, 8, VarSeqKind::Seq2, ); Self { client } } pub fn new_serial(port: &str) -> Self { let client = HostClient::new_serial_cobs(port, ERROR_PATH, 8, 9600, VarSeqKind::Seq2); Self { client } } pub async fn wait_closed(&self) { self.client.wait_closed().await; } pub async fn ping(&self, id: u32) -> Result> { let val = self.client.send_resp::(&id).await?; Ok(val) } pub async fn get_id(&self) -> Result> { let id = self.client.send_resp::(&()).await?; Ok(id) } pub async fn set_rgb_single( &self, position: u32, r: u8, g: u8, b: u8, ) -> Result<(), WorkbookError> { self.client .send_resp::(&SingleLed { position, rgb: Rgb8 { r, g, b }, }) .await? .flatten() } pub async fn set_all_rgb_single( &self, r: u8, g: u8, b: u8, ) -> Result<(), WorkbookError> { self.client .send_resp::(&[Rgb8 { r, g, b }; 24]) .await?; Ok(()) } pub async fn start_accelerometer( &self, interval_ms: u32, range: AccelRange, ) -> Result<(), WorkbookError> { self.client .send_resp::(&StartAccel { interval_ms, range }) .await?; Ok(()) } pub async fn stop_accelerometer(&self) -> Result> { let res = self .client .send_resp::(&()) .await?; Ok(res) } } impl Default for WorkbookClient { fn default() -> Self { Self::new() } }