rust_lum/src/main.rs
2022-01-22 16:17:37 +01:00

126 lines
3.8 KiB
Rust

use bluer::{AdapterEvent, Device};
use bluer::gatt::remote::Characteristic;
use futures::{pin_mut, StreamExt};
use std::time::Duration;
use tokio::time::sleep;
const SERVICE_UUID: bluer::Uuid = bluer::Uuid::from_u128(0xadaf0900c33242a893bd25e905756cb8);
const PIXEL_DATA_UUID: bluer::Uuid = bluer::Uuid::from_u128(0xadaf0903c33242a893bd25e905756cb8);
#[tokio::main(flavor = "current_thread")]
async fn main() -> bluer::Result<()> {
let session = bluer::Session::new().await?;
let adapter_names = session.adapter_names().await?;
let adapter_name = adapter_names.first().expect("no Bluetooth adapter found");
let adapter = session.adapter(adapter_name)?;
adapter.set_powered(true).await?;
let discover = adapter.discover_devices().await?;
pin_mut!(discover);
while let Some(evt) = discover.next().await {
match evt {
AdapterEvent::DeviceAdded(addr) => {
let device = adapter.device(addr)?;
match find_neopixel_service(&device).await {
Ok(Some(char)) => {
println!("found characteristic");
match send_seq(&char).await {
// this loop should never stop
_ => ()
}
}
Ok(None) => {
println!("characteristic not found")
}
Err(err) => {
println!("device error : {}", &err);
let _ = adapter.remove_device(device.address()).await;
}
}
}
AdapterEvent::DeviceRemoved(addr) => {
println!("Device removed {}", addr);
}
_ => (),
}
}
Ok(())
}
async fn send_seq(char: &Characteristic) -> bluer::Result<()> {
println!(" Characteristic flags : {:?}, ", char.flags().await?);
let mut base_data: Vec<u8> = vec![0x00, 0x00, 0x01];
let mut off_data: Vec<u8> = vec![0x00, 0x00, 0x01];
for _ in 0..10 {
base_data.append(&mut vec![0xff, 0x00, 0x00]);
off_data.append(&mut vec![0x00, 0x00, 0x00]);
}
loop {
char.write(&*base_data).await?;
sleep(Duration::from_secs(1)).await;
char.write(&*off_data).await?;
sleep(Duration::from_secs(1)).await;
}
}
async fn connect(device: &Device, retries: u8) -> bluer::Result<()> {
if device.is_connected().await? {
return Ok(())
}
for i in 0..retries {
match device.connect().await {
Ok(()) => return Ok(()),
Err(_) => {
println!("connection error ({}), retry…", i);
}
}
}
Err(bluer::Error {
kind: bluer::ErrorKind::ConnectionAttemptFailed,
message: "all attempts fail".parse().unwrap(),
})
}
async fn find_neopixel_service(device: &Device) -> bluer::Result<Option<Characteristic>> {
let addr = device.address();
let uuids = device.uuids().await?.unwrap_or_default();
if uuids.contains(&SERVICE_UUID) {
println!("service neopixel found for device {}", &addr);
match connect(device, 3).await {
Ok(()) => {
println!("successefully connected");
}
Err(err) => {
println!("unable to connect, trying new device, {}", err);
return Err(err)
}
}
for service in device.services().await? {
if SERVICE_UUID == service.uuid().await? {
for char in service.characteristics().await? {
if PIXEL_DATA_UUID == char.uuid().await? {
return Ok(Some(char));
}
}
}
}
}
Ok(None)
}