use std::sync::Arc; use btleplug::{ api::{Central as _, Peripheral as _}, platform::PeripheralId, }; pub 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>>, ) -> 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>>, ) -> Result { 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.get_connected_peripheral().await, }) } else { Ok(CentralState::default()) } } #[tauri::command] pub async fn connected_peripheral_state( app_state: State<'_, Arc>>, ) -> Result, errors::AppError> { let state = app_state.read().await; let connected_peripheral = state .connected_peripheral .lock() .await .clone() .ok_or(errors::AppError::NoConnectedPeripheral)?; let central = state .get_central_adapter() .await .ok_or(errors::AppError::BluetoothAdapterNotFound)?; if let Ok(peripheral) = central.peripheral(&connected_peripheral).await { let properties = peripheral .properties() .await .map_err(|_| errors::AppError::UnableToRetrievePeripheralProperties)?; Ok(Some( PeripheralItem::new(&peripheral, properties.as_ref()).await, )) } else { Ok(None) } } #[tauri::command] pub async fn specific_peripheral_state( app_state: State<'_, Arc>>, id: PeripheralId, ) -> Result { let state = app_state.read().await; let central = state .get_central_adapter() .await .ok_or(errors::AppError::BluetoothAdapterNotFound)?; let peripheral = central .peripheral(&id) .await .map_err(|_| errors::AppError::UnableToRetrievePeripheralState)?; let properties = peripheral.properties().await.unwrap_or(None); Ok(PeripheralItem::new(&peripheral, properties.as_ref()).await) } #[tauri::command] pub async fn channel_a_state( _app_state: State<'_, Arc>>, ) -> Result { Ok(ChannelState::default()) } #[tauri::command] pub async fn channel_b_state( _app_state: State<'_, Arc>>, ) -> Result { Ok(ChannelState::default()) } #[tauri::command] pub async fn start_scan_devices( app_handle: AppHandle, app_state: State<'_, Arc>>, ) -> 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>>, ) -> Result<(), errors::AppError> { bluetooth::stop_scan(Arc::new(app_handle), app_state).await?; Ok(()) }