mirror of
https://github.com/jhbruhn/catprint-rs.git
synced 2025-03-15 02:45:49 +00:00
113 lines
3.4 KiB
Rust
113 lines
3.4 KiB
Rust
|
use btleplug::api::{Central, Manager as _, Peripheral};
|
||
|
use btleplug::platform::Manager;
|
||
|
use std::collections::VecDeque;
|
||
|
use std::error::Error;
|
||
|
use std::time::Duration;
|
||
|
use tokio::time;
|
||
|
use uuid::Uuid;
|
||
|
|
||
|
const TX_CHARACTERISTIC_UUID: Uuid = Uuid::from_u128(0x0000ae01_0000_1000_8000_00805f9b34fb);
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub struct Device {
|
||
|
peripheral: btleplug::platform::Peripheral,
|
||
|
tx_buffer: VecDeque<u8>,
|
||
|
}
|
||
|
|
||
|
impl Device {
|
||
|
pub async fn find(manager: &mut Manager, name: &str) -> Result<Device, Box<dyn Error>> {
|
||
|
let mut device_result = Err("Could not connect to device".into());
|
||
|
let adapter_list = manager.adapters().await?;
|
||
|
if adapter_list.is_empty() {
|
||
|
device_result = Err("No Bluetooth adapters found".into());
|
||
|
}
|
||
|
|
||
|
for adapter in adapter_list.iter() {
|
||
|
println!("Starting scan...");
|
||
|
adapter
|
||
|
.start_scan()
|
||
|
.await
|
||
|
.expect("Can't scan BLE adapter for connected devices...");
|
||
|
time::sleep(Duration::from_secs(2)).await;
|
||
|
|
||
|
let peripherals = adapter.peripherals().await?;
|
||
|
for peripheral in peripherals {
|
||
|
let properties = peripheral.properties().await?;
|
||
|
|
||
|
if let Some(properties) = properties {
|
||
|
if let Some(local_name) = properties.local_name {
|
||
|
if local_name.contains(name) {
|
||
|
if !peripheral.is_connected().await? {
|
||
|
peripheral.connect().await?;
|
||
|
}
|
||
|
let _ = peripheral.discover_characteristics().await?;
|
||
|
device_result = Ok(Device {
|
||
|
peripheral,
|
||
|
tx_buffer: VecDeque::new(),
|
||
|
});
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
device_result
|
||
|
}
|
||
|
|
||
|
pub fn queue_command(&mut self, command: crate::protocol::Command) {
|
||
|
self.tx_buffer.extend(&command.to_bytes())
|
||
|
}
|
||
|
|
||
|
pub fn queue_commands(&mut self, commands: &[crate::protocol::Command]) {
|
||
|
for command in commands {
|
||
|
self.queue_command(*command)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub async fn flush(&mut self) -> Result<(), Box<dyn Error>> {
|
||
|
const MTU_SIZE: usize = 20;
|
||
|
|
||
|
while !self.tx_buffer.is_empty() {
|
||
|
let mut buf = Vec::with_capacity(MTU_SIZE);
|
||
|
for _ in 0..MTU_SIZE {
|
||
|
if let Some(byte) = self.tx_buffer.pop_front() {
|
||
|
buf.push(byte);
|
||
|
} else {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// this could be nicer i guess
|
||
|
}
|
||
|
|
||
|
self.tx(&buf).await?;
|
||
|
}
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
async fn tx(&mut self, data: &[u8]) -> Result<(), Box<dyn Error>> {
|
||
|
let characteristics = self.peripheral.characteristics();
|
||
|
|
||
|
let tx_characteristic = characteristics
|
||
|
.iter()
|
||
|
.filter(|c| c.uuid == TX_CHARACTERISTIC_UUID)
|
||
|
.next()
|
||
|
.unwrap();
|
||
|
|
||
|
self.peripheral
|
||
|
.write(
|
||
|
&tx_characteristic,
|
||
|
data,
|
||
|
btleplug::api::WriteType::WithoutResponse,
|
||
|
)
|
||
|
.await?;
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
pub async fn destroy(self) {
|
||
|
self.peripheral.disconnect().await.unwrap();
|
||
|
}
|
||
|
}
|