Rust蓝牙通信库bluez-generated的使用,bluez-generated提供与Linux蓝牙协议栈BlueZ的高效交互接口
Rust蓝牙通信库bluez-generated的使用
bluez-generated是为Linux蓝牙协议栈BlueZ生成的异步D-Bus绑定库,提供了与BlueZ高效交互的接口。
基本介绍
bluez-generated库具有以下特点:
- 通过D-Bus与BlueZ交互
- 基于异步编程模型
- 通过自省数据生成绑定接口
- 目前仅包含作者测试过的设备接口
安装
在Cargo.toml中添加依赖:
bluez-generated = "0.4.0"
或者运行命令:
cargo add bluez-generated
完整示例代码
以下是一个使用bluez-generated进行蓝牙设备扫描的完整示例:
use bluez_generated::{
org_bluez::{
Adapter1Proxy,
Device1Proxy,
ObjectManagerProxy
},
OrgBluezObjectManager,
OrgFreedesktopDBusObjectManager,
};
use dbus::nonblock::SyncConnection;
use dbus_tokio::connection;
use futures::stream::StreamExt;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 建立D-Bus连接
let (resource, conn) = connection::new_system_sync()?;
// 在后台运行连接
tokio::spawn(async {
let err = resource.await;
panic!("Lost connection to D-Bus: {}", err);
});
// 获取对象管理器代理
let proxy = ObjectManagerProxy::new(&conn, "/");
// 获取所有管理对象
let objects = proxy.get_managed_objects().await?;
// 查找蓝牙适配器
let adapter_path = objects.keys()
.find(|path| path.to_string().contains("hci0"))
.ok_or("No Bluetooth adapter found")?;
// 创建适配器代理
let adapter = Adapter1Proxy::new(&conn, adapter_path.clone());
// 设置适配器为可发现模式
adapter.set_discoverable(true).await?;
// 开始扫描设备
adapter.start_discovery().await?;
// 监听设备添加事件
let mut device_added = proxy.receive_interfaces_added().await;
tokio::spawn(async move {
while let Some(signal) = device_added.next().await {
if let Some(device_proxy) = Device1Proxy::from_path(&conn, signal.path.clone()) {
if let Ok(properties) = device_proxy.get_all().await {
println!("Found device: {:?}", properties.address);
}
}
}
});
// 持续扫描10秒
tokio::time::sleep(Duration::from_secs(10)).await;
// 停止扫描
adapter.stop_discovery().await?;
Ok(())
}
添加新接口
如果需要使用bluez-generated未包含的接口,可以按照以下步骤添加:
- 参考项目中的introspect.sh脚本生成新接口
- 提交Pull Request或直接在你的项目中包含生成的接口文件
许可证
bluez-generated采用双重许可:
- Apache License 2.0
- MIT license
未来发展方向
- 目前仅支持异步绑定,未来可能添加阻塞式绑定
- 计划为PropertiesChanged信号生成强类型绑定,便于订阅属性变更事件
贡献
欢迎贡献代码,所有提交默认采用上述双重许可。
完整示例代码(连接并读取蓝牙设备属性)
以下是另一个完整示例,展示如何连接已发现的蓝牙设备并读取其属性:
use bluez_generated::{
org_bluez::{
Adapter1Proxy,
Device1Proxy,
ObjectManagerProxy
},
OrgBluezObjectManager,
OrgFreedesktopDBusObjectManager,
};
use dbus::nonblock::SyncConnection;
use dbus_tokio::connection;
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 建立D-Bus系统连接
let (resource, conn) = connection::new_system_sync()?;
// 后台运行D-Bus连接
tokio::spawn(async {
let err = resource.await;
panic!("Lost connection to D-Bus: {}", err);
});
// 创建对象管理器代理
let manager = ObjectManagerProxy::new(&conn, "/");
// 获取所有已配对的蓝牙设备
let objects = manager.get_managed_objects().await?;
// 打印所有已配对设备
for (path, _) in objects.iter() {
if let Some(device) = Device1Proxy::from_path(&conn, path.clone()) {
if let Ok(props) = device.get_all().await {
println!("Paired device: {} ({})", props.alias.unwrap_or_default(), props.address);
}
}
}
// 查找特定设备(示例: 查找名为"MyDevice"的设备)
let device_path = objects.keys()
.find(|path| {
if let Some(device) = Device1Proxy::from_path(&conn, path.clone()) {
if let Ok(props) = device.get_all().await {
return props.alias.as_ref().map_or(false, |a| a == "MyDevice");
}
}
false
})
.ok_or("Device not found")?;
// 创建设备代理
let device = Device1Proxy::new(&conn, device_path.clone());
// 连接设备
device.connect().await?;
println!("Device connected successfully");
// 获取并打印设备属性
let properties = device.get_all().await?;
println!("Device properties: {:#?}", properties);
// 保持连接5秒
tokio::time::sleep(Duration::from_secs(5)).await;
// 断开连接
device.disconnect().await?;
println!("Device disconnected");
Ok(())
}
1 回复