bleasy/
characteristic.rs

1use btleplug::{
2    api::{Characteristic as BtleCharacteristic, Peripheral as _, WriteType},
3    platform::Peripheral,
4    Result,
5};
6use std::pin::Pin;
7use tokio_stream::{Stream, StreamExt};
8use uuid::Uuid;
9
10#[derive(Debug, Clone)]
11pub struct Characteristic {
12    pub(crate) peripheral: Peripheral,
13    pub(crate) characteristic: BtleCharacteristic,
14}
15
16impl Characteristic {
17    pub async fn read(&self) -> Result<Vec<u8>> {
18        self.peripheral.read(&self.characteristic).await
19    }
20
21    pub async fn write_request(&self, data: &[u8]) -> Result<()> {
22        self.write(data, WriteType::WithResponse).await
23    }
24
25    pub async fn write_command(&self, data: &[u8]) -> Result<()> {
26        self.write(data, WriteType::WithoutResponse).await
27    }
28
29    #[inline]
30    async fn write(&self, data: &[u8], write_type: WriteType) -> Result<()> {
31        self.peripheral
32            .write(&self.characteristic, data, write_type)
33            .await
34    }
35
36    pub async fn subscribe(&self) -> Result<Pin<Box<dyn Stream<Item = Vec<u8>> + Send>>> {
37        self.peripheral.subscribe(&self.characteristic).await?;
38
39        let stream = self.peripheral.notifications().await?;
40        let uuid = self.characteristic.uuid;
41
42        Ok(Box::pin(stream.filter_map(move |n| {
43            if n.uuid == uuid {
44                Some(n.value)
45            } else {
46                None
47            }
48        })))
49    }
50
51    #[inline]
52    pub async fn unsubscribe(&self) -> Result<()> {
53        self.peripheral.unsubscribe(&self.characteristic).await
54    }
55
56    pub fn uuid(&self) -> Uuid {
57        self.characteristic.uuid
58    }
59}