| // Copyright 2023 Google LLC |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| //! Contains traits that are used to find and connect to Low Energy Peers, i.e. the GAP Central |
| //! and Observer roles role defined in the Bluetooth Core Specification |
| //! (5.4, Volume 3 Part C Section 2.2.2) |
| //! |
| //! These traits should be implemented outside this crate, conforming to the types and structs here |
| //! when necessary. |
| |
| use crate::client::Client; |
| use crate::types::*; |
| |
| use bt_common::{PeerId, Uuid}; |
| use futures::{Future, Stream}; |
| |
| #[derive(Debug, Clone)] |
| pub enum AdvertisingDatum { |
| Services(Vec<Uuid>), |
| ServiceData(Uuid, Vec<u8>), |
| ManufacturerData(u16, Vec<u8>), |
| // TODO: Update to a more structured Appearance |
| Appearance(u16), |
| TxPowerLevel(i8), |
| Uri(String), |
| } |
| |
| /// Matches a single advertised attribute or condition from a Bluetooth Low Energy peer. |
| #[derive(Clone, Debug)] |
| pub enum Filter { |
| /// Advertised Service UUID |
| ServiceUuid(Uuid), |
| /// ServiceData is included which is associated with the UUID |
| HasServiceData(Uuid), |
| /// ManufacturerData is provided with the Company Identifier Code given |
| HasManufacturerData(u16), |
| /// Connectable flag is set |
| IsConnectable, |
| /// String provided is included in the peer's name |
| MatchesName(String), |
| /// Path loss from the peer (RSSI - Advertised TX Power) is below the given dB value |
| MaxPathLoss(i8), |
| } |
| |
| /// A ScanFilter must match all of its combined filters and conditions to provide a result. |
| /// Currently can only include zero or more Filters. |
| /// The Default ScanFilter will match everything and should be avoided. |
| #[derive(Default, Clone, Debug)] |
| pub struct ScanFilter { |
| pub filters: Vec<Filter>, |
| } |
| |
| impl From<Filter> for ScanFilter { |
| fn from(value: Filter) -> Self { |
| ScanFilter { filters: vec![value] } |
| } |
| } |
| |
| impl ScanFilter { |
| pub fn add(&mut self, filter: Filter) -> &mut Self { |
| self.filters.push(filter); |
| self |
| } |
| } |
| |
| #[derive(Debug, Clone)] |
| pub enum PeerName { |
| Unknown, |
| PartialName(String), |
| CompleteName(String), |
| } |
| |
| #[derive(Debug, Clone)] |
| pub struct ScanResult { |
| pub id: PeerId, |
| pub connectable: bool, |
| pub name: PeerName, |
| pub advertised: Vec<AdvertisingDatum>, |
| } |
| |
| pub trait Central { |
| type ScanResultStream: Stream<Item = Result<ScanResult>> + 'static; |
| type Client: Client; |
| type ClientFut: Future<Output = Result<Self::Client>>; |
| |
| /// Scan for peers. |
| /// If any of the filters match, the results will be returned in the Stream. |
| fn scan(&self, filters: &[ScanFilter]) -> Self::ScanResultStream; |
| |
| /// Connect to a specific peer. |
| fn connect(&self, peer_id: PeerId) -> Self::ClientFut; |
| } |