use windows::core::GUID;
use windows::Devices::Bluetooth::BluetoothCacheMode;
use windows::Devices::Bluetooth::GenericAttributeProfile::GattDeviceService;
use super::error::check_communication_status;
use crate::error::ErrorKind;
use crate::{Characteristic, Result, Service, Uuid};
#[derive(Clone)]
pub struct ServiceImpl {
inner: GattDeviceService,
}
impl PartialEq for ServiceImpl {
fn eq(&self, other: &Self) -> bool {
self.inner.Session().unwrap() == other.inner.Session().unwrap()
&& self.inner.AttributeHandle().unwrap() == other.inner.AttributeHandle().unwrap()
}
}
impl Eq for ServiceImpl {}
impl std::hash::Hash for ServiceImpl {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.inner
.Session()
.unwrap()
.DeviceId()
.unwrap()
.Id()
.unwrap()
.to_os_string()
.hash(state);
self.inner.AttributeHandle().unwrap().hash(state);
}
}
impl std::fmt::Debug for ServiceImpl {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Service")
.field(
"device_id",
&self
.inner
.Session()
.expect("Session missing on GattDeviceService")
.DeviceId()
.expect("DeviceId missing on GattSession")
.Id()
.expect("Id missing on BluetoothDeviceId")
.to_os_string(),
)
.field("uuid", &self.inner.Uuid().expect("UUID missing on GattDeviceService"))
.field(
"handle",
&self
.inner
.AttributeHandle()
.expect("AttributeHandle missing on GattDeviceService"),
)
.finish()
}
}
impl Service {
pub(super) fn new(service: GattDeviceService) -> Self {
Service(ServiceImpl { inner: service })
}
}
impl ServiceImpl {
pub fn uuid(&self) -> Uuid {
Uuid::from_u128(self.inner.Uuid().expect("UUID missing on GattDeviceService").to_u128())
}
pub async fn uuid_async(&self) -> Result<Uuid> {
Ok(Uuid::from_u128(self.inner.Uuid()?.to_u128()))
}
pub async fn is_primary(&self) -> Result<bool> {
Err(ErrorKind::NotSupported.into())
}
pub async fn discover_characteristics(&self) -> Result<Vec<Characteristic>> {
let res = self
.inner
.GetCharacteristicsWithCacheModeAsync(BluetoothCacheMode::Uncached)?
.await?;
check_communication_status(res.Status()?, res.ProtocolError(), "discovering characteristics")?;
let characteristics = res.Characteristics()?;
Ok(characteristics.into_iter().map(Characteristic::new).collect())
}
pub async fn discover_characteristics_with_uuid(&self, uuid: Uuid) -> Result<Vec<Characteristic>> {
let res = self
.inner
.GetCharacteristicsForUuidWithCacheModeAsync(GUID::from_u128(uuid.as_u128()), BluetoothCacheMode::Uncached)?
.await?;
check_communication_status(res.Status()?, res.ProtocolError(), "discovering characteristics")?;
let characteristics = res.Characteristics()?;
Ok(characteristics.into_iter().map(Characteristic::new).collect())
}
pub async fn characteristics(&self) -> Result<Vec<Characteristic>> {
let res = self
.inner
.GetCharacteristicsWithCacheModeAsync(BluetoothCacheMode::Cached)?
.await?;
check_communication_status(res.Status()?, res.ProtocolError(), "discovering characteristics")?;
let characteristics = res.Characteristics()?;
Ok(characteristics.into_iter().map(Characteristic::new).collect())
}
pub async fn discover_included_services(&self) -> Result<Vec<Service>> {
let res = self
.inner
.GetIncludedServicesWithCacheModeAsync(BluetoothCacheMode::Uncached)?
.await?;
check_communication_status(res.Status()?, res.ProtocolError(), "discovering included services")?;
let services = res.Services()?;
Ok(services.into_iter().map(Service::new).collect())
}
pub async fn discover_included_services_with_uuid(&self, uuid: Uuid) -> Result<Vec<Service>> {
let res = self
.inner
.GetIncludedServicesForUuidWithCacheModeAsync(
GUID::from_u128(uuid.as_u128()),
BluetoothCacheMode::Uncached,
)?
.await?;
check_communication_status(res.Status()?, res.ProtocolError(), "discovering included services")?;
let services = res.Services()?;
Ok(services.into_iter().map(Service::new).collect())
}
pub async fn included_services(&self) -> Result<Vec<Service>> {
let res = self
.inner
.GetIncludedServicesWithCacheModeAsync(BluetoothCacheMode::Cached)?
.await?;
check_communication_status(res.Status()?, res.ProtocolError(), "discovering included services")?;
let services = res.Services()?;
Ok(services.into_iter().map(Service::new).collect())
}
}