4.Rust嵌入式入门——蓝牙服务
这一节将利用BLE蓝牙技术来提供一项服务,使得我们能够通过应用程序来控制灯光的开启与关闭。
前置知识
不了解蓝牙的同学可以先了解一点蓝牙知识。
sdk配置
在项目目录下的sdkconfig.defaults文件中添加下面配置
CONFIG_BT_ENABLED=y
CONFIG_BT_BLE_ENABLED=y
CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_ENABLED=y
安装依赖
cargo add esp32-nimble
蓝牙服务
新建bin/ble_server.rs
use std::sync::{ Arc, Mutex };
use esp_idf_svc::hal::delay::FreeRtos;
use rgb::RGB8;
use rust_embedded_study::{ init, led::WS2812RMT };
use esp32_nimble::{ utilities::BleUuid, BLEAdvertisementData, BLEDevice, NimbleProperties };
fn main() -> anyhow::Result<()> {
// 初始化系统、外设和NVS flash。
let (_sys, peripherals, _nvs) = init()?;
// 获取BLE设备实例
let device = BLEDevice::take();
// 初始化LED灯
let led = Arc::new(
Mutex::new(WS2812RMT::new(peripherals.pins.gpio8, peripherals.rmt.channel0)?)
);
// 获取并配置BLE的广告实例
let advertising = device.get_advertising();
// 获取并配置BLE的服务实例。
let server = device.get_server();
// 配置BLE连接时的回调函数
server.on_connect(|server, desc| {
log::info!("on_connect: {:#?}", desc);
server.update_conn_params(desc.conn_handle(), 24, 48, 0, 60).unwrap();
if server.connected_count() < (esp_idf_svc::sys::CONFIG_BT_NIMBLE_MAX_CONNECTIONS as _) {
advertising.lock().start().unwrap();
}
});
// 配置BLE断开连接时的回调函数
server.on_disconnect(|desc, reason| {
log::warn!("on_disconnect: {:#?}, reason: {:#?}", desc, reason)
});
// 创建BLE服务,使用UUID 0x8848
let service = server.create_service(BleUuid::from_uuid16(0x8848));
// 在服务中创建一个特性,用于设置LED颜色,使用UUID 0xffa1
let set_color_characteristic = service
.lock()
.create_characteristic(
BleUuid::from_uuid16(0xffa1),
NimbleProperties::WRITE | NimbleProperties::READ
);
// 在服务中创建一个特性,用于关闭LED,使用UUID 0xffa2
let close_characteristic = service
.lock()
.create_characteristic(BleUuid::from_uuid16(0xffa2), NimbleProperties::WRITE);
// 当设置颜色特性被写入时,更新LED的颜色。
let write_led = led.clone();
set_color_characteristic
.lock()
.on_write(move |args| {
let data = args.recv_data();
match write_led.lock().unwrap().set_pixel(RGB8::new(data[0], data[1], data[2])) {
Ok(_) => {
log::warn!("Set LED color to {:?}", RGB8::new(data[0], data[1], data[2]))
}
Err(e) => log::error!("Error: {}", e),
}
})
.on_read(|value, desc| {
log::warn!("Read from descriptor {:?}", desc);
value.set_value(b"hello world")
});
// 当关闭特性被写入时,关闭LED。
close_characteristic.lock().on_write(move |args| {
let data = args.recv_data();
if data[0] == 1 {
match led.lock().unwrap().shutdown() {
Ok(_) => { log::warn!("Close LED {:?}", data) }
Err(e) => log::error!("Error: {}", e),
}
}
});
// 配置广告数据并启动广告
advertising
.lock()
.set_data(
BLEAdvertisementData::new().name("ESP32").add_service_uuid(BleUuid::from_uuid16(0x8848))
)?;
advertising.lock().start()?;
// 打印蓝牙服务相关日志
server.ble_gatts_show_local();
loop {
FreeRtos::delay_ms(10000);
}
}
- 程序首先进行系统、外设和NVS flash的初始化。
- 获取BLE设备实例,并初始化LED灯。
- 获取并配置BLE的广告实例和服务实例。
- 配置BLE连接和断开连接时的回调函数。
- 创建BLE服务,并在服务中创建两个特性:一个用于设置LED颜色,一个用于关闭LED。
- 当设置颜色特性被写入时,更新LED的颜色;当关闭特性被写入时,关闭LED。
- 配置广告数据并启动广告。
- 程序进入循环等待状态。
然后写入开发板
cargo run --bin ble_server
蓝牙调试工具的相关信息可以参考以下文章:
然后只需按照规定向这些服务和特性写入相应的值即可。
最后
🎉恭喜您成功实现了蓝牙服务功能。您所探索的代码可以在GitHub仓库yexiyue/rust-embedded-study中找到。
如果您觉得不错,请点个关注或者收藏,感谢您的支持。