// 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 // // http://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 anyhow::anyhow; use bumble::{ adv::{AdvertisementDataBuilder, CommonDataType}, wrapper::{ device::Device, logging::{bumble_env_logging_level, py_logging_basic_config}, transport::Transport, }, }; use clap::Parser as _; use pyo3::PyResult; use rand::Rng; use std::path; #[pyo3_asyncio::tokio::main] async fn main() -> PyResult<()> { env_logger::builder() .filter_level(log::LevelFilter::Info) .init(); let cli = Cli::parse(); if cli.log_hci { py_logging_basic_config(bumble_env_logging_level("DEBUG"))?; } let transport = Transport::open(cli.transport).await?; let mut device = Device::from_config_file_with_hci( &cli.device_config, transport.source()?, transport.sink()?, )?; let mut adv_data = AdvertisementDataBuilder::new(); adv_data .append( CommonDataType::CompleteLocalName, "Bumble from Rust".as_bytes(), ) .map_err(|e| anyhow!(e))?; // Randomized TX power adv_data .append( CommonDataType::TxPowerLevel, &[rand::thread_rng().gen_range(-100_i8..=20) as u8], ) .map_err(|e| anyhow!(e))?; device.power_on().await?; if cli.extended { println!("Starting extended advertisement..."); device.start_advertising_extended(adv_data).await?; } else { device.set_advertising_data(adv_data)?; println!("Starting legacy advertisement..."); device.start_advertising(true).await?; } // wait until user kills the process tokio::signal::ctrl_c().await?; if cli.extended { println!("Stopping extended advertisement..."); device.stop_advertising_extended().await?; } else { println!("Stopping legacy advertisement..."); device.stop_advertising().await?; } Ok(()) } #[derive(clap::Parser)] #[command(author, version, about, long_about = None)] struct Cli { /// Bumble device config. /// /// See, for instance, `examples/device1.json` in the Python project. #[arg(long)] device_config: path::PathBuf, /// Bumble transport spec. /// /// #[arg(long)] transport: String, /// Whether to perform an extended (BT 5.0) advertisement #[arg(long)] extended: bool, /// Log HCI commands #[arg(long)] log_hci: bool, }