autd3-protobuf 27.0.0

Protocol Buffer
Documentation
use std::net::SocketAddr;

use autd3_driver::{
    derive::*,
    geometry::{Device, Geometry, IntoDevice},
};

use crate::{traits::*, OpenRequestLightweight};

pub struct LightweightClient {
    client: crate::pb::ecat_light_client::EcatLightClient<tonic::transport::Channel>,
    geometry: Geometry,
}

#[derive(Builder)]
pub struct LightweightClientBuilder {
    devices: Vec<Device>,
    #[get]
    #[set]
    parallel_threshold: usize,
    #[get]
    #[set]
    send_interval: std::time::Duration,
    #[cfg(target_os = "windows")]
    #[get]
    #[set]
    timer_resolution: u32,
}

impl LightweightClientBuilder {
    fn new<D: IntoDevice, F: IntoIterator<Item = D>>(iter: F) -> Self {
        Self {
            devices: iter
                .into_iter()
                .enumerate()
                .map(|(i, d)| d.into_device(i))
                .collect(),
            parallel_threshold: 4,
            send_interval: std::time::Duration::from_millis(1),
            #[cfg(target_os = "windows")]
            timer_resolution: 1,
        }
    }

    pub async fn open(
        self,
        addr: SocketAddr,
    ) -> Result<LightweightClient, crate::error::AUTDProtoBufError> {
        LightweightClient::open_impl(self, addr).await
    }
}

impl LightweightClient {
    pub fn builder<D: IntoDevice, F: IntoIterator<Item = D>>(iter: F) -> LightweightClientBuilder {
        LightweightClientBuilder::new(iter)
    }

    async fn open_impl(
        builder: LightweightClientBuilder,
        addr: SocketAddr,
    ) -> Result<Self, crate::error::AUTDProtoBufError> {
        let mut client =
            crate::pb::ecat_light_client::EcatLightClient::connect(format!("http://{}", addr))
                .await?;
        let geometry = Geometry::new(builder.devices);
        let res = client
            .open(OpenRequestLightweight {
                geometry: Some(geometry.to_msg(None)),
                parallel_threshold: builder.parallel_threshold as _,
                send_interval: builder.send_interval.as_nanos() as _,
                #[cfg(target_os = "windows")]
                timer_resolution: builder.timer_resolution,
                #[cfg(not(target_os = "windows"))]
                timer_resolution: 1,
            })
            .await?
            .into_inner();
        if !res.success {
            return Err(crate::error::AUTDProtoBufError::SendError(res.msg));
        }
        Ok(Self { client, geometry })
    }

    pub async fn firmware_version(
        &mut self,
    ) -> Result<
        Vec<autd3_driver::firmware::version::FirmwareVersion>,
        crate::error::AUTDProtoBufError,
    > {
        let res = self
            .client
            .firmware_version(tonic::Request::new(
                crate::pb::FirmwareVersionRequestLightweight {},
            ))
            .await?
            .into_inner();
        if !res.success {
            return Err(crate::error::AUTDProtoBufError::SendError(res.msg));
        }
        Vec::from_msg(&res)
    }

    pub async fn send(
        &mut self,
        datagram: impl ToMessage<Message = crate::pb::Datagram>,
    ) -> Result<bool, crate::error::AUTDProtoBufError> {
        let res = self
            .client
            .send(tonic::Request::new(datagram.to_msg(Some(&self.geometry))))
            .await?
            .into_inner();
        if res.err {
            return Err(crate::error::AUTDProtoBufError::SendError(res.msg));
        }
        Ok(res.success)
    }

    pub async fn close(mut self) -> Result<(), crate::error::AUTDProtoBufError> {
        let res = self
            .client
            .close(crate::pb::CloseRequestLightweight {})
            .await?
            .into_inner();
        if !res.success {
            return Err(crate::error::AUTDProtoBufError::SendError(res.msg));
        }
        Ok(())
    }
}