mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-15 07:06:11 -04:00
Merge pull request #1951 from google:revert-1950-revert-1867-fpwinrs_seeker
PiperOrigin-RevId: 548204543
This commit is contained in:
@@ -47,6 +47,16 @@ jobs:
|
||||
submodules: recursive
|
||||
- name: Build FPP
|
||||
run: cargo build --manifest-path presence/fpp/fpp/Cargo.toml
|
||||
- name: Build Fairpair
|
||||
- name: Build Fast Pair
|
||||
run: cargo build --manifest-path fastpair/rust/Cargo.toml
|
||||
|
||||
|
||||
build-rust-windows:
|
||||
name: Build Rust on Windows
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Build Fast Pair
|
||||
run: cargo build --manifest-path fastpair/rust/Cargo.toml
|
||||
|
||||
@@ -47,3 +47,9 @@ Carthage/Build
|
||||
.UlyssesRoot
|
||||
.Ulysses-Settings.plist
|
||||
.Ulysses-Group.plist
|
||||
|
||||
# IntelliJ
|
||||
.idea
|
||||
|
||||
# Rust
|
||||
Cargo.lock
|
||||
@@ -0,0 +1,2 @@
|
||||
# Build files
|
||||
target
|
||||
@@ -20,3 +20,15 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0"
|
||||
futures = { version = "0.3", features = ["executor"] }
|
||||
tracing = "0.1.37"
|
||||
cfg-if = "1.0.0"
|
||||
async-trait = "0.1"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows = { version = "0.48", features = [
|
||||
"Devices_Bluetooth",
|
||||
"Devices_Bluetooth_Advertisement",
|
||||
"Foundation",
|
||||
] }
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
max_width = 80
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
/// Concrete types implementing this trait are Bluetooth Central devices.
|
||||
/// They provide methods for retrieving nearby connections and device info.
|
||||
#[async_trait]
|
||||
pub trait Adapter: Sized {
|
||||
type Device: Device;
|
||||
|
||||
/// Retrieve the system-default Bluetooth adapter.
|
||||
async fn default() -> Result<Self, anyhow::Error>;
|
||||
|
||||
/// Begin scanning for nearby devices.
|
||||
fn start_scan_devices(&mut self) -> Result<(), anyhow::Error>;
|
||||
|
||||
/// Stop scanning for nearby devices.
|
||||
fn stop_scan_devices(&mut self) -> Result<(), anyhow::Error>;
|
||||
|
||||
/// Poll next discovered device.
|
||||
async fn next_device(&mut self) -> Result<Self::Device, anyhow::Error>;
|
||||
}
|
||||
|
||||
/// Concrete types implementing this trait represent Bluetooth Peripheral devices.
|
||||
/// They provide methods for retrieving device info and running device actions,
|
||||
/// such as pairing.
|
||||
pub trait Device {
|
||||
/// Retrieve the name advertised by this device.
|
||||
fn name(&self) -> Result<String, anyhow::Error>;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Split into separate crate once demo is finished, providing custom error types
|
||||
// instead of using anyhow.
|
||||
// b/290070686
|
||||
|
||||
pub mod common;
|
||||
|
||||
pub use common::{Adapter, Device};
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(windows)] {
|
||||
mod windows_ble;
|
||||
use windows_ble::BleAdapter;
|
||||
} else {
|
||||
mod unsupported;
|
||||
use unsupported::BleAdapter;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn default_adapter() -> Result<impl Adapter, anyhow::Error> {
|
||||
BleAdapter::default().await
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use async_trait::async_trait;
|
||||
|
||||
use super::BleDevice;
|
||||
use crate::bluetooth::common::Adapter;
|
||||
|
||||
/// Concrete type implementing `Adapter`, used for unsupported devices.
|
||||
/// Every method should panic.
|
||||
pub struct BleAdapter;
|
||||
|
||||
#[async_trait]
|
||||
impl Adapter for BleAdapter {
|
||||
type Device = BleDevice;
|
||||
|
||||
async fn default() -> Result<Self, anyhow::Error> {
|
||||
panic!("Unsupported target platform.");
|
||||
}
|
||||
|
||||
fn start_scan_devices(&mut self) -> Result<(), anyhow::Error> {
|
||||
panic!("Unsupported target platform.");
|
||||
}
|
||||
|
||||
fn stop_scan_devices(&mut self) -> Result<(), anyhow::Error> {
|
||||
panic!("Unsupported target platform.");
|
||||
}
|
||||
|
||||
async fn next_device(&mut self) -> Result<Self::Device, anyhow::Error> {
|
||||
panic!("Unsupported target platform.");
|
||||
}
|
||||
}
|
||||
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// TODO b/288592509 unit tests
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use crate::bluetooth::common::Device;
|
||||
|
||||
/// Concrete type implementing `Device`, used for unsupported devices.
|
||||
/// Every method should panic.
|
||||
pub struct BleDevice;
|
||||
|
||||
impl Device for BleDevice {
|
||||
fn name(&self) -> Result<String, anyhow::Error> {
|
||||
panic!("Unsupported target platform.")
|
||||
}
|
||||
}
|
||||
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// TODO b/288592509 unit tests
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bluetooth LE module for unsupported devices. Every method panics.
|
||||
mod adapter;
|
||||
mod device;
|
||||
|
||||
pub use adapter::*;
|
||||
pub use device::*;
|
||||
@@ -0,0 +1,222 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use futures::{stream::Stream, StreamExt};
|
||||
use tracing::{error, warn};
|
||||
use windows::{
|
||||
Devices::Bluetooth::{
|
||||
Advertisement::{
|
||||
// Struct that receives Bluetooth Low Energy (LE) advertisements.
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementwatcher?view=winrt-22621
|
||||
BluetoothLEAdvertisementReceivedEventArgs,
|
||||
|
||||
// Enum describing the type of advertisement (connectable, directed, etc).
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothaddresstype?view=winrt-22621
|
||||
BluetoothLEAdvertisementType,
|
||||
|
||||
// Provides data for a Received event on a `BluetoothLEAdvertisementWatcher`.
|
||||
// Instance is created when the Received event occurs in the watcher struct.
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementreceivedeventargs?view=winrt-22621
|
||||
BluetoothLEAdvertisementWatcher,
|
||||
|
||||
// Provides data for a Stopped event on a `BluetoothLEAdvertisementWatcher`.
|
||||
// Instance is created when the Stopped event occurs on a watcher struct.
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothleadvertisementwatcherstoppedeventargs?view=winrt-22621
|
||||
BluetoothLEAdvertisementWatcherStoppedEventArgs,
|
||||
|
||||
// Defines constants that specify a Bluetooth LE scanning mode.
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.advertisement.bluetoothlescanningmode?view=winrt-22621
|
||||
BluetoothLEScanningMode,
|
||||
},
|
||||
// Struct for obtaining global constant information about a computer's
|
||||
// Bluetooth adapter.
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothadapter?view=winrt-22621
|
||||
BluetoothAdapter,
|
||||
},
|
||||
// Wraps a closure for handling events associated with a struct
|
||||
// (e.g. Received and Stopped events in BluetoothLEAdvertisementWatcher).
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.foundation.typedeventhandler-2?view=winrt-22621
|
||||
Foundation::TypedEventHandler,
|
||||
};
|
||||
|
||||
use super::BleDevice;
|
||||
use crate::bluetooth::common::Adapter;
|
||||
|
||||
/// Concrete type implementing `Adapter`, used for Windows BLE.
|
||||
pub struct BleAdapter {
|
||||
inner: BluetoothAdapter,
|
||||
// NOTE: Using Boxed dyn here is silly because only one concrete type ever
|
||||
// used. Change this to `impl Stream` once impl trait return types
|
||||
// stabilized for existential types.
|
||||
// b/289224233.
|
||||
device_stream: Option<Pin<Box<dyn Stream<Item = BleDevice> + Send + Sync>>>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Adapter for BleAdapter {
|
||||
type Device = BleDevice;
|
||||
|
||||
async fn default() -> Result<Self, anyhow::Error> {
|
||||
let inner = BluetoothAdapter::GetDefaultAsync()?.await?;
|
||||
|
||||
if !inner.IsLowEnergySupported()? {
|
||||
return Err(anyhow::anyhow!(
|
||||
"This device's Bluetooth Adapter doesn't support Bluetooth LE Transport type."
|
||||
));
|
||||
}
|
||||
if !inner.IsCentralRoleSupported()? {
|
||||
return Err(anyhow::anyhow!(
|
||||
"This device's Bluetooth Adapter doesn't support Bluetooth LE central role."
|
||||
));
|
||||
}
|
||||
|
||||
Ok(BleAdapter {
|
||||
inner,
|
||||
device_stream: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn start_scan_devices(&mut self) -> Result<(), anyhow::Error> {
|
||||
let watcher = BluetoothLEAdvertisementWatcher::new()?;
|
||||
match watcher.SetScanningMode(BluetoothLEScanningMode::Active) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
warn!("Failed to turn on active scanning. Error: {}", err)
|
||||
}
|
||||
};
|
||||
|
||||
if self.inner.IsExtendedAdvertisingSupported()? {
|
||||
watcher.SetAllowExtendedAdvertisements(true)?;
|
||||
}
|
||||
|
||||
// `futures::channel::mpsc` is like `std::sync::mpsc` but `impl Stream`.
|
||||
let (sender, receiver) = futures::channel::mpsc::channel(16);
|
||||
let sender = Arc::new(std::sync::Mutex::new(sender));
|
||||
|
||||
// `received_handler` closure holds non-owning channel reference, to
|
||||
// ensure `stopped_handler` can close the channel when
|
||||
// `received_handler` is done.
|
||||
let weak_sender = Arc::downgrade(&sender);
|
||||
let received_handler = TypedEventHandler::new(
|
||||
// Move `weak_sender` into closure.
|
||||
move |watcher: &Option<BluetoothLEAdvertisementWatcher>,
|
||||
event_args: &Option<
|
||||
BluetoothLEAdvertisementReceivedEventArgs,
|
||||
>| {
|
||||
if watcher.is_some() {
|
||||
if let Some(event_args) = event_args {
|
||||
if let Some(sender) = weak_sender.upgrade() {
|
||||
match sender
|
||||
.lock()
|
||||
.unwrap()
|
||||
.try_send(event_args.clone())
|
||||
{
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
error!("Error while handling Received event: {:?}", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
|
||||
// `stopped_handler` closure owns channel reference, can close channel.
|
||||
let mut sender = Some(sender);
|
||||
let stopped_handler = TypedEventHandler::new(
|
||||
// Move `sender` into closure.
|
||||
move |_watcher,
|
||||
_event_args: &Option<
|
||||
BluetoothLEAdvertisementWatcherStoppedEventArgs,
|
||||
>| {
|
||||
// Drop `sender`, closing the channel.
|
||||
let _sender = sender.take();
|
||||
println!("Watcher stopped receiving BLE advertisements.");
|
||||
Ok(())
|
||||
},
|
||||
);
|
||||
|
||||
watcher.Received(&received_handler)?;
|
||||
watcher.Stopped(&stopped_handler)?;
|
||||
watcher.Start()?;
|
||||
|
||||
// `receiver` is a `futures::channel::mpsc::Receiver`, which implements
|
||||
// `futures::stream::Stream`. This is essentially an async Iterator.
|
||||
// We apply a FilterMap to map from advertisement packet to a future
|
||||
// returning `BleDevice` and filter out undesired connections. We need a
|
||||
// pinned box to satisfy trait bounds for `Stream`.
|
||||
self.device_stream =
|
||||
Some(Box::pin(receiver.filter_map(move |event_args| {
|
||||
// Move `watcher` into `FilterMap` closure. This ensures `watcher`
|
||||
// is only dropped when the stream is closed.
|
||||
let _watcher = &watcher;
|
||||
|
||||
// Move `event_args` into async block.
|
||||
async move {
|
||||
match event_args.AdvertisementType().ok()? {
|
||||
BluetoothLEAdvertisementType::NonConnectableUndirected => {
|
||||
None
|
||||
}
|
||||
_ => {
|
||||
let addr = event_args.BluetoothAddress().ok()?;
|
||||
let kind = event_args.BluetoothAddressType().ok()?;
|
||||
|
||||
match BleDevice::from_addr(addr, kind).await {
|
||||
Ok(device) => Some(device),
|
||||
Err(err) => {
|
||||
warn!("Error creating device: {:?}", err);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn stop_scan_devices(&mut self) -> Result<(), anyhow::Error> {
|
||||
if let Some(_) = &self.device_stream {
|
||||
self.device_stream.take();
|
||||
Ok(())
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Device scanning hasn't started."))
|
||||
}
|
||||
}
|
||||
|
||||
async fn next_device(&mut self) -> Result<Self::Device, anyhow::Error> {
|
||||
if let Some(stream) = &mut self.device_stream {
|
||||
stream
|
||||
.next()
|
||||
.await
|
||||
.ok_or(anyhow::anyhow!("Device returned from stream is None."))
|
||||
} else {
|
||||
Err(anyhow::anyhow!("Device scanning hasn't started."))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// TODO b/288592509 unit tests
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use async_trait::async_trait;
|
||||
use windows::Devices::Bluetooth::{
|
||||
// Enum describing the type of address (public, random, unspecified).
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothaddresstype?view=winrt-22621
|
||||
BluetoothAddressType,
|
||||
|
||||
// Struct for interacting with and pairing to a discovered BLE device.
|
||||
// https://learn.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothledevice?view=winrt-22621
|
||||
BluetoothLEDevice,
|
||||
};
|
||||
|
||||
use crate::bluetooth::common::Device;
|
||||
|
||||
/// Concrete type implementing `Device`, used for Windows BLE.
|
||||
pub struct BleDevice {
|
||||
inner: BluetoothLEDevice,
|
||||
}
|
||||
|
||||
impl BleDevice {
|
||||
/// Create a `BleDevice` instance from the raw bluetooth address information.
|
||||
pub(super) async fn from_addr(
|
||||
addr: u64,
|
||||
kind: BluetoothAddressType,
|
||||
) -> Result<Self, anyhow::Error> {
|
||||
let inner =
|
||||
BluetoothLEDevice::FromBluetoothAddressWithBluetoothAddressTypeAsync(addr, kind)?
|
||||
.await?;
|
||||
|
||||
Ok(BleDevice { inner })
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Device for BleDevice {
|
||||
fn name(&self) -> Result<String, anyhow::Error> {
|
||||
Ok(self.inner.Name()?.to_string_lossy())
|
||||
}
|
||||
}
|
||||
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// TODO b/288592509 unit tests
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Bluetooth LE module for Windows devices.
|
||||
mod adapter;
|
||||
mod device;
|
||||
|
||||
pub use adapter::*;
|
||||
pub use device::*;
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Library file, exports modules for use in integration tests and external crates.
|
||||
pub mod bluetooth;
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2020 Google LLC
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@@ -12,9 +12,23 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod message_stream;
|
||||
mod types;
|
||||
use futures::executor;
|
||||
|
||||
fn main() {
|
||||
println!("Fastpair Rust!");
|
||||
mod bluetooth;
|
||||
|
||||
use bluetooth::{Adapter, Device};
|
||||
|
||||
fn main() -> Result<(), anyhow::Error> {
|
||||
let run = async {
|
||||
let mut adapter = bluetooth::default_adapter().await?;
|
||||
adapter.start_scan_devices()?;
|
||||
|
||||
while let Ok(device) = adapter.next_device().await {
|
||||
println!("found {}", device.name()?)
|
||||
}
|
||||
|
||||
unreachable!("Done scanning");
|
||||
};
|
||||
|
||||
executor::block_on(run)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use fastpair::*;
|
||||
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
// TODO b/288592509 write integration tests
|
||||
}
|
||||
Reference in New Issue
Block a user