estim_control/src-tauri/src/cmd/mod.rs
2025-02-26 06:38:13 +08:00

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(())
}