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>>, ) -> 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 .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>>, ) -> Result, 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>>, ) -> Result, errors::AppError> { let state = app_state.read().await; let central = state.get_central_adapter().await; let mut peripherals: Vec = 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>>, ) -> 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(()) }