blob: 5197556a2b89f4d2d92b1f50143b57108943011f [file] [log] [blame]
// 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;
}