use bumble::wrapper::{
device::{Device, Peer},
hci::{packets::AddressType, Address},
profile::BatteryServiceProxy,
transport::Transport,
PyObjectExt,
};
use clap::Parser as _;
use log::info;
use owo_colors::OwoColorize;
use pyo3::prelude::*;
#[pyo3_asyncio::tokio::main]
async fn main() -> PyResult<()> {
env_logger::builder()
.filter_level(log::LevelFilter::Info)
.init();
let cli = Cli::parse();
let transport = Transport::open(cli.transport).await?;
let address = Address::new("F0:F1:F2:F3:F4:F5", AddressType::RandomDeviceAddress)?;
let device = Device::with_hci("Bumble", address, transport.source()?, transport.sink()?)?;
device.power_on().await?;
let conn = device.connect(&cli.target_addr).await?;
let mut peer = Peer::new(conn)?;
for mut s in peer.discover_services().await? {
s.discover_characteristics().await?;
}
let battery_service = peer
.create_service_proxy::<BatteryServiceProxy>()?
.ok_or(anyhow::anyhow!("No battery service found"))?;
let mut battery_level_char = battery_service
.battery_level()?
.ok_or(anyhow::anyhow!("No battery level characteristic"))?;
info!(
"{} {}",
"Initial Battery Level:".green(),
battery_level_char
.read_value()
.await?
.extract_with_gil::<u32>()?
);
battery_level_char
.subscribe(|_py, args| {
info!(
"{} {:?}",
"Battery level update:".green(),
args.get_item(0)?.extract::<u32>()?,
);
Ok(())
})
.await?;
tokio::signal::ctrl_c().await?;
Ok(())
}
#[derive(clap::Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[arg(long)]
transport: String,
#[arg(long)]
target_addr: String,
}