use super::super::utils;
use crate::{Error, Result, api::Descriptor};
use std::future::IntoFuture;
use uuid::Uuid;
use windows::{
Devices::Bluetooth::{
BluetoothCacheMode,
GenericAttributeProfile::{GattCommunicationStatus, GattDescriptor},
},
Storage::Streams::{DataReader, DataWriter},
};
#[derive(Debug)]
pub struct BLEDescriptor {
descriptor: GattDescriptor,
}
impl BLEDescriptor {
pub fn new(descriptor: GattDescriptor) -> Self {
Self { descriptor }
}
pub fn uuid(&self) -> Uuid {
utils::to_uuid(&self.descriptor.Uuid().unwrap())
}
pub fn to_descriptor(&self, service_uuid: Uuid, characteristic_uuid: Uuid) -> Descriptor {
let uuid = self.uuid();
Descriptor {
uuid,
service_uuid,
characteristic_uuid,
}
}
pub async fn write_value(&self, data: &[u8]) -> Result<()> {
let writer = DataWriter::new()?;
writer.WriteBytes(data)?;
let operation = self.descriptor.WriteValueAsync(&writer.DetachBuffer()?)?;
let result = operation.into_future().await?;
if result == GattCommunicationStatus::Success {
Ok(())
} else {
Err(Error::Other(
format!("Windows UWP threw error on write descriptor: {:?}", result).into(),
))
}
}
pub async fn read_value(&self) -> Result<Vec<u8>> {
let result = self
.descriptor
.ReadValueWithCacheModeAsync(BluetoothCacheMode::Uncached)?
.into_future()
.await?;
if result.Status()? == GattCommunicationStatus::Success {
let value = result.Value()?;
let reader = DataReader::FromBuffer(&value)?;
let len = reader.UnconsumedBufferLength()? as usize;
let mut input = vec![0u8; len];
reader.ReadBytes(&mut input[0..len])?;
Ok(input)
} else {
Err(Error::Other(
format!("Windows UWP threw error on read: {:?}", result).into(),
))
}
}
}