163 lines
5.3 KiB
Rust
163 lines
5.3 KiB
Rust
use std::sync::Arc;
|
|
|
|
use btleplug::api::{Central as _, Peripheral as _};
|
|
use state::{CentralState, ChannelState, PeripheralItem};
|
|
use tauri::{async_runtime::RwLock, AppHandle, Emitter, State};
|
|
|
|
use crate::{bluetooth, errors, state::AppState};
|
|
|
|
mod state;
|
|
|
|
#[tauri::command]
|
|
pub async fn activate_central_adapter(
|
|
app_handle: AppHandle,
|
|
app_state: State<'_, Arc<RwLock<AppState>>>,
|
|
) -> Result<(), errors::AppError> {
|
|
let app = Arc::new(app_handle);
|
|
let adapter = bluetooth::get_central_adapter().await?;
|
|
{
|
|
let state = app_state.read().await;
|
|
state.set_central_adapter(adapter).await;
|
|
state.clear_central_event_handler().await;
|
|
}
|
|
let handle =
|
|
bluetooth::handle_bluetooth_events(Arc::clone(&app), Arc::clone(&app_state)).await?;
|
|
{
|
|
let state = app_state.write().await;
|
|
state.set_central_event_handler(handle).await;
|
|
}
|
|
app.emit("central_state_updated", ()).unwrap();
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn central_device_state(
|
|
app_state: State<'_, Arc<RwLock<AppState>>>,
|
|
) -> Result<CentralState, errors::AppError> {
|
|
let state = app_state.read().await;
|
|
let central = state.get_central_adapter().await;
|
|
if let Some(central) = central {
|
|
let central_device_state = central
|
|
.adapter_state()
|
|
.await
|
|
.map_err(|_| errors::AppError::BluetoothNotReady)?;
|
|
Ok(CentralState {
|
|
is_ready: central_device_state == btleplug::api::CentralState::PoweredOn,
|
|
is_scanning: *state.scanning.lock().await,
|
|
connected: state
|
|
.connected_peripheral
|
|
.lock()
|
|
.await
|
|
.clone()
|
|
.map(|p| p.id()),
|
|
})
|
|
} else {
|
|
Ok(CentralState::default())
|
|
}
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn connected_peripheral_state(
|
|
app_state: State<'_, Arc<RwLock<AppState>>>,
|
|
) -> Result<Option<PeripheralItem>, errors::AppError> {
|
|
let state = app_state.read().await;
|
|
let connected_peripheral = state.connected_peripheral.lock().await.clone();
|
|
if let Some(peripheral) = connected_peripheral {
|
|
let properties = peripheral
|
|
.properties()
|
|
.await
|
|
.map_err(|_| errors::AppError::UnableToRetrievePeripheralProperties)?;
|
|
if let Some(properties) = properties {
|
|
let represent = properties
|
|
.local_name
|
|
.unwrap_or_else(|| properties.address.to_string());
|
|
Ok(Some(PeripheralItem {
|
|
id: peripheral.id(),
|
|
address: properties.address.to_string(),
|
|
represent,
|
|
is_connected: peripheral
|
|
.is_connected()
|
|
.await
|
|
.map_err(|_| errors::AppError::UnableToRetrievePeripheralProperties)?,
|
|
rssi: properties.rssi,
|
|
battery: properties.tx_power_level,
|
|
}))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn found_peripherals(
|
|
app_state: State<'_, Arc<RwLock<AppState>>>,
|
|
) -> Result<Vec<PeripheralItem>, errors::AppError> {
|
|
let state = app_state.read().await;
|
|
let central = state.get_central_adapter().await;
|
|
let mut peripherals: Vec<PeripheralItem> = vec![];
|
|
if let Some(central) = central {
|
|
let found_peripherals = central
|
|
.peripherals()
|
|
.await
|
|
.map_err(|_| errors::AppError::UnableToRetrievePeripherals)?;
|
|
for peripheral in found_peripherals {
|
|
let properties = peripheral
|
|
.properties()
|
|
.await
|
|
.map_err(|_| errors::AppError::UnableToRetrievePeripheralProperties)?;
|
|
if let Some(properties) = properties {
|
|
let represent = properties
|
|
.local_name
|
|
.unwrap_or_else(|| properties.address.to_string());
|
|
let item = PeripheralItem {
|
|
id: peripheral.id(),
|
|
address: properties.address.to_string(),
|
|
represent,
|
|
is_connected: peripheral
|
|
.is_connected()
|
|
.await
|
|
.map_err(|_| errors::AppError::UnableToRetrievePeripheralProperties)?,
|
|
rssi: properties.rssi,
|
|
battery: properties.tx_power_level,
|
|
};
|
|
peripherals.push(item);
|
|
}
|
|
}
|
|
}
|
|
Ok(peripherals)
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn channel_a_state(
|
|
_app_state: State<'_, Arc<RwLock<AppState>>>,
|
|
) -> Result<ChannelState, errors::AppError> {
|
|
Ok(ChannelState::default())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn channel_b_state(
|
|
_app_state: State<'_, Arc<RwLock<AppState>>>,
|
|
) -> Result<ChannelState, errors::AppError> {
|
|
Ok(ChannelState::default())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn start_scan_devices(
|
|
app_handle: AppHandle,
|
|
app_state: State<'_, Arc<RwLock<AppState>>>,
|
|
) -> Result<(), errors::AppError> {
|
|
bluetooth::start_scan(Arc::new(app_handle), app_state).await?;
|
|
Ok(())
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn stop_scan_devices(
|
|
app_handle: AppHandle,
|
|
app_state: State<'_, Arc<RwLock<AppState>>>,
|
|
) -> Result<(), errors::AppError> {
|
|
bluetooth::stop_scan(Arc::new(app_handle), app_state).await?;
|
|
Ok(())
|
|
}
|