diff --git a/src-tauri/src/bluetooth.rs b/src-tauri/src/bluetooth.rs index 3ed95b9..f7f7f12 100644 --- a/src-tauri/src/bluetooth.rs +++ b/src-tauri/src/bluetooth.rs @@ -27,7 +27,7 @@ pub async fn handle_bluetooth_events( while let Some(event) = event_stream.next().await { match event { btleplug::api::CentralEvent::DeviceDiscovered(_id) => { - app.emit("app_state_updated", ()).unwrap(); + app.emit("peripheral_found", ()).unwrap(); } btleplug::api::CentralEvent::DeviceConnected(_id) => { let state = app_state.write().await; @@ -36,7 +36,7 @@ pub async fn handle_bluetooth_events( for peripheral in peripherals { if peripheral.id() == _id { state.set_connected_peripheral(peripheral).await; - app.emit("app_state_updated", ()).unwrap(); + app.emit("peripheral_connected", ()).unwrap(); break; } } @@ -45,14 +45,14 @@ pub async fn handle_bluetooth_events( btleplug::api::CentralEvent::DeviceDisconnected(_id) => { let state = app_state.write().await; state.clear_connected_peripheral().await; - app.emit("app_state_updated", ()).unwrap(); + app.emit("peripheral_disconnected", ()).unwrap(); } _ => {} } } })) } else { - app.emit("app_state_updated", ()).unwrap(); + app.emit("central_state_updated", ()).unwrap(); Err(errors::AppError::BluetoothNotReady) } } @@ -91,8 +91,8 @@ pub async fn start_scan( .start_scan(ScanFilter::default()) .await .map_err(|_| errors::AppError::UnableToStartScan)?; - app_handle.emit("app_state_updated", ()).unwrap(); state.set_scanning(true).await; + app_handle.emit("scanning_started", ()).unwrap(); Ok(()) } else { Err(errors::AppError::NoAvailableBluetoothAdapter) @@ -110,8 +110,8 @@ pub async fn stop_scan( .stop_scan() .await .map_err(|_| errors::AppError::UnableToStopScan)?; - app_handle.emit("app_state_updated", ()).unwrap(); state.set_scanning(false).await; + app_handle.emit("scanning_stopped", ()).unwrap(); Ok(()) } else { Err(errors::AppError::NoAvailableBluetoothAdapter) diff --git a/src-tauri/src/cmd/mod.rs b/src-tauri/src/cmd/mod.rs index b94341e..bba1794 100644 --- a/src-tauri/src/cmd/mod.rs +++ b/src-tauri/src/cmd/mod.rs @@ -1,7 +1,7 @@ use std::sync::Arc; use btleplug::api::{Central as _, Peripheral as _}; -use state::{ApplicationState, CentralState, ChannelState, PeripheralItem}; +use state::{CentralState, ChannelState, PeripheralItem}; use tauri::{async_runtime::RwLock, AppHandle, Emitter, State}; use crate::{bluetooth, errors, state::AppState}; @@ -23,28 +23,81 @@ pub async fn activate_central_adapter( let handle = bluetooth::handle_bluetooth_events(Arc::clone(&app), Arc::clone(&app_state)).await?; { - let state = app_state.write().await; // Changed from lock() to write() + let state = app_state.write().await; state.set_central_event_handler(handle).await; } - app.emit("app_state_updated", ()).unwrap(); + app.emit("central_state_updated", ()).unwrap(); Ok(()) } #[tauri::command] -pub async fn refresh_application_state( +pub async fn central_device_state( app_state: State<'_, Arc>>, -) -> Result { +) -> Result { let state = app_state.read().await; - let mut peripherals: Vec = vec![]; - let mut connected_peripheral = None; - let central = state.get_central_adapter().await; - let central_state = if let Some(central) = central { + 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 @@ -69,38 +122,25 @@ pub async fn refresh_application_state( rssi: properties.rssi, battery: properties.tx_power_level, }; - if peripheral - .is_connected() - .await - .map_err(|_| errors::AppError::UnableToRetrievePeripheralState)? - { - connected_peripheral = Some(item.clone()); - } peripherals.push(item); } } + } + Ok(peripherals) +} - 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 { - CentralState::default() - }; +#[tauri::command] +pub async fn channel_a_state( + _app_state: State<'_, Arc>>, +) -> Result { + Ok(ChannelState::default()) +} - Ok(ApplicationState { - central: central_state, - peripherals, - connected_peripheral, - channel_a: ChannelState::default(), - channel_b: ChannelState::default(), - }) +#[tauri::command] +pub async fn channel_b_state( + _app_state: State<'_, Arc>>, +) -> Result { + Ok(ChannelState::default()) } #[tauri::command] diff --git a/src-tauri/src/cmd/state.rs b/src-tauri/src/cmd/state.rs index 1dde792..2fd8e1d 100644 --- a/src-tauri/src/cmd/state.rs +++ b/src-tauri/src/cmd/state.rs @@ -4,6 +4,7 @@ use serde::Serialize; use crate::playlist::PlayMode; #[derive(Debug, Clone, Default, Serialize)] +#[serde(rename_all = "camelCase")] pub struct CentralState { pub is_ready: bool, pub is_scanning: bool, @@ -11,6 +12,7 @@ pub struct CentralState { } #[derive(Debug, Clone, Serialize)] +#[serde(rename_all = "camelCase")] pub struct PeripheralItem { pub id: PeripheralId, pub address: String, @@ -21,6 +23,7 @@ pub struct PeripheralItem { } #[derive(Debug, Clone, Default, Serialize)] +#[serde(rename_all = "camelCase")] pub struct ChannelState { pub is_playing: bool, pub strength: u32, @@ -30,12 +33,3 @@ pub struct ChannelState { pub boost_limit: u32, pub play_mode: PlayMode, } - -#[derive(Debug, Clone, Serialize)] -pub struct ApplicationState { - pub central: CentralState, - pub peripherals: Vec, - pub connected_peripheral: Option, - pub channel_a: ChannelState, - pub channel_b: ChannelState, -} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 0229bed..37df5c4 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -53,7 +53,11 @@ pub fn run() { Ok(()) }) .invoke_handler(generate_handler![ - cmd::refresh_application_state, + cmd::central_device_state, + cmd::connected_peripheral_state, + cmd::found_peripherals, + cmd::channel_a_state, + cmd::channel_b_state, cmd::activate_central_adapter, cmd::start_scan_devices, cmd::stop_scan_devices