#![allow(clippy::let_unit_value)]
use futures_util::Stream;
use crate::{sys, AdapterEvent, AdvertisingDevice, Device, DeviceId, Result, Uuid};
/// The system's Bluetooth adapter interface.
///
/// The default adapter for the system may be accessed with the [`Adapter::default()`] method.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Adapter(sys::adapter::AdapterImpl);
impl Adapter {
/// Creates an interface to the default Bluetooth adapter for the system
#[inline]
pub async fn default() -> Option<Self> {
sys::adapter::AdapterImpl::default().await.map(Adapter)
}
/// A stream of [`AdapterEvent`] which allows the application to identify when the adapter is enabled or disabled.
#[inline]
pub async fn events(&self) -> Result<impl Stream<Item = Result<AdapterEvent>> + '_> {
self.0.events().await
}
/// Asynchronously blocks until the adapter is available
#[inline]
pub async fn wait_available(&self) -> Result<()> {
self.0.wait_available().await
}
/// Attempts to create the device identified by `id`
#[inline]
pub async fn open_device(&self, id: &DeviceId) -> Result<Device> {
self.0.open_device(id).await
}
/// Finds all connected Bluetooth LE devices
#[inline]
pub async fn connected_devices(&self) -> Result<Vec<Device>> {
self.0.connected_devices().await
}
/// Finds all connected devices providing any service in `services`
///
/// # Panics
///
/// Panics if `services` is empty.
#[inline]
pub async fn connected_devices_with_services(&self, services: &[Uuid]) -> Result<Vec<Device>> {
self.0.connected_devices_with_services(services).await
}
/// Starts scanning for Bluetooth advertising packets.
///
/// Returns a stream of [`AdvertisingDevice`] structs which contain the data from the advertising packet and the
/// [`Device`] which sent it. Scanning is automatically stopped when the stream is dropped. Inclusion of duplicate
/// packets is a platform-specific implementation detail.
///
/// If `services` is not empty, returns advertisements including at least one GATT service with a UUID in
/// `services`. Otherwise returns all advertisements.
#[inline]
pub async fn scan<'a>(&'a self, services: &'a [Uuid]) -> Result<impl Stream<Item = AdvertisingDevice> + 'a> {
self.0.scan(services).await
}
/// Finds Bluetooth devices providing any service in `services`.
///
/// Returns a stream of [`Device`] structs with matching connected devices returned first. If the stream is not
/// dropped before all matching connected devices are consumed then scanning will begin for devices advertising any
/// of the `services`. Scanning will continue until the stream is dropped. Inclusion of duplicate devices is a
/// platform-specific implementation detail.
#[inline]
pub async fn discover_devices<'a>(
&'a self,
services: &'a [Uuid],
) -> Result<impl Stream<Item = Result<Device>> + 'a> {
self.0.discover_devices(services).await
}
/// Connects to the [`Device`]
///
/// # Platform specifics
///
/// ## MacOS/iOS
///
/// This method must be called before any methods on the [`Device`] which require a connection are called. After a
/// successful return from this method, a connection has been established with the device (if one did not already
/// exist) and the application can then interact with the device. This connection will be maintained until either
/// [`disconnect_device`][Self::disconnect_device] is called or the `Adapter` is dropped.
///
/// ## Windows
///
/// On Windows, device connections are automatically managed by the OS. This method has no effect. Instead, a
/// connection will automatically be established, if necessary, when methods on the device requiring a connection
/// are called.
///
/// ## Linux
///
/// If the device is not yet connected to the system, this method must be called before any methods on the
/// [`Device`] which require a connection are called. After a successful return from this method, a connection has
/// been established with the device (if one did not already exist) and the application can then interact with the
/// device. This connection will be maintained until [`disconnect_device`][Self::disconnect_device] is called.
#[inline]
pub async fn connect_device(&self, device: &Device) -> Result<()> {
self.0.connect_device(device).await
}
/// Disconnects from the [`Device`]
///
/// # Platform specifics
///
/// ## MacOS/iOS
///
/// Once this method is called, the application will no longer have access to the [`Device`] and any methods
/// which would require a connection will fail. If no other application has a connection to the same device,
/// the underlying Bluetooth connection will be closed.
///
/// ## Windows
///
/// On Windows, device connections are automatically managed by the OS. This method has no effect. Instead, the
/// connection will be closed only when the [`Device`] and all its child objects are dropped.
///
/// ## Linux
///
/// This method disconnects the device from the system, even if other applications are using the device.
#[inline]
pub async fn disconnect_device(&self, device: &Device) -> Result<()> {
self.0.disconnect_device(device).await
}
}