use le_stream::ToLeStream;
use tokio::sync::mpsc::Sender;
use tokio::sync::oneshot::channel;
use zb_core::short_id::Device;
use zb_core::{ClusterSpecific, ExpectResponse};
use zb_zdp::Command;
use crate::zdp::{Message, Payload};
use crate::{CommunicationResponse, Coordinator, Error};
pub type ZdpResponse<T> = CommunicationResponse<Command, T>;
pub trait Zdp {
fn communicate<T>(
&self,
device: Device,
request: T,
) -> impl Future<Output = Result<ZdpResponse<T::Response>, Error>> + Send
where
T: ClusterSpecific + ExpectResponse<Command> + ToLeStream;
}
impl Zdp for Sender<Message> {
fn communicate<T>(
&self,
device: Device,
command: T,
) -> impl Future<Output = Result<ZdpResponse<T::Response>, Error>> + Send
where
T: ClusterSpecific + ExpectResponse<Command> + ToLeStream,
{
let (response, result) = channel();
let payload = Payload::from(command);
async move {
self.send(Message::Communicate {
device,
payload,
response,
})
.await?;
Ok(result.await??.into())
}
}
}
impl Zdp for Coordinator {
fn communicate<T>(
&self,
device: Device,
command: T,
) -> impl Future<Output = Result<ZdpResponse<T::Response>, Error>> + Send
where
T: ClusterSpecific + ExpectResponse<Command> + ToLeStream,
{
self.zdp.communicate(device, command)
}
}