corebluetooth-async 0.1.0

An asynchronous wrapper for the `corebluetooth` crate
use std::error::Error;
use std::pin::pin;

use corebluetooth::dispatch::DispatchQoS;
use corebluetooth_async::CentralManagerAsync;
use futures_lite::StreamExt;
use objc2_core_bluetooth::CBManagerState;
use tracing::info;
use tracing::metadata::LevelFilter;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    use tracing_subscriber::prelude::*;
    use tracing_subscriber::{EnvFilter, fmt};

    tracing_subscriber::registry()
        .with(fmt::layer())
        .with(
            EnvFilter::builder()
                .with_default_directive(LevelFilter::INFO.into())
                .from_env_lossy(),
        )
        .init();

    let task =
        CentralManagerAsync::background(DispatchQoS::default(), false, |central, executor| {
            let task = async move {
                if central.state() != CBManagerState::PoweredOn {
                    let mut updates = pin!(central.state_updates());
                    loop {
                        let state = updates.next().await.unwrap();
                        if state == CBManagerState::PoweredOn {
                            break;
                        }
                    }
                }

                info!("starting scan");
                let mut scan = pin!(central.scan(None, true, None));
                info!("scan started");
                while let Some(did_discover) = scan.next().await {
                    info!(
                        "{}{}: {:?}",
                        did_discover
                            .peripheral
                            .name()
                            .as_deref()
                            .unwrap_or("(unknown)"),
                        format!(" ({}dBm)", did_discover.rssi),
                        did_discover.advertisement_data
                    );
                }
            };

            unsafe { executor.spawn_local(task) }
        });

    task.await;
    Ok(())
}