refactor state refresh mechanism.
This commit is contained in:
parent
4f5420b658
commit
d9a4f92c04
|
@ -27,7 +27,7 @@ pub async fn handle_bluetooth_events(
|
||||||
while let Some(event) = event_stream.next().await {
|
while let Some(event) = event_stream.next().await {
|
||||||
match event {
|
match event {
|
||||||
btleplug::api::CentralEvent::DeviceDiscovered(_id) => {
|
btleplug::api::CentralEvent::DeviceDiscovered(_id) => {
|
||||||
app.emit("app_state_updated", ()).unwrap();
|
app.emit("peripheral_found", ()).unwrap();
|
||||||
}
|
}
|
||||||
btleplug::api::CentralEvent::DeviceConnected(_id) => {
|
btleplug::api::CentralEvent::DeviceConnected(_id) => {
|
||||||
let state = app_state.write().await;
|
let state = app_state.write().await;
|
||||||
|
@ -36,7 +36,7 @@ pub async fn handle_bluetooth_events(
|
||||||
for peripheral in peripherals {
|
for peripheral in peripherals {
|
||||||
if peripheral.id() == _id {
|
if peripheral.id() == _id {
|
||||||
state.set_connected_peripheral(peripheral).await;
|
state.set_connected_peripheral(peripheral).await;
|
||||||
app.emit("app_state_updated", ()).unwrap();
|
app.emit("peripheral_connected", ()).unwrap();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,14 +45,14 @@ pub async fn handle_bluetooth_events(
|
||||||
btleplug::api::CentralEvent::DeviceDisconnected(_id) => {
|
btleplug::api::CentralEvent::DeviceDisconnected(_id) => {
|
||||||
let state = app_state.write().await;
|
let state = app_state.write().await;
|
||||||
state.clear_connected_peripheral().await;
|
state.clear_connected_peripheral().await;
|
||||||
app.emit("app_state_updated", ()).unwrap();
|
app.emit("peripheral_disconnected", ()).unwrap();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
app.emit("app_state_updated", ()).unwrap();
|
app.emit("central_state_updated", ()).unwrap();
|
||||||
Err(errors::AppError::BluetoothNotReady)
|
Err(errors::AppError::BluetoothNotReady)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,8 +91,8 @@ pub async fn start_scan(
|
||||||
.start_scan(ScanFilter::default())
|
.start_scan(ScanFilter::default())
|
||||||
.await
|
.await
|
||||||
.map_err(|_| errors::AppError::UnableToStartScan)?;
|
.map_err(|_| errors::AppError::UnableToStartScan)?;
|
||||||
app_handle.emit("app_state_updated", ()).unwrap();
|
|
||||||
state.set_scanning(true).await;
|
state.set_scanning(true).await;
|
||||||
|
app_handle.emit("scanning_started", ()).unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(errors::AppError::NoAvailableBluetoothAdapter)
|
Err(errors::AppError::NoAvailableBluetoothAdapter)
|
||||||
|
@ -110,8 +110,8 @@ pub async fn stop_scan(
|
||||||
.stop_scan()
|
.stop_scan()
|
||||||
.await
|
.await
|
||||||
.map_err(|_| errors::AppError::UnableToStopScan)?;
|
.map_err(|_| errors::AppError::UnableToStopScan)?;
|
||||||
app_handle.emit("app_state_updated", ()).unwrap();
|
|
||||||
state.set_scanning(false).await;
|
state.set_scanning(false).await;
|
||||||
|
app_handle.emit("scanning_stopped", ()).unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err(errors::AppError::NoAvailableBluetoothAdapter)
|
Err(errors::AppError::NoAvailableBluetoothAdapter)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use btleplug::api::{Central as _, Peripheral as _};
|
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 tauri::{async_runtime::RwLock, AppHandle, Emitter, State};
|
||||||
|
|
||||||
use crate::{bluetooth, errors, state::AppState};
|
use crate::{bluetooth, errors, state::AppState};
|
||||||
|
@ -23,28 +23,81 @@ pub async fn activate_central_adapter(
|
||||||
let handle =
|
let handle =
|
||||||
bluetooth::handle_bluetooth_events(Arc::clone(&app), Arc::clone(&app_state)).await?;
|
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;
|
state.set_central_event_handler(handle).await;
|
||||||
}
|
}
|
||||||
app.emit("app_state_updated", ()).unwrap();
|
app.emit("central_state_updated", ()).unwrap();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn refresh_application_state(
|
pub async fn central_device_state(
|
||||||
app_state: State<'_, Arc<RwLock<AppState>>>,
|
app_state: State<'_, Arc<RwLock<AppState>>>,
|
||||||
) -> Result<ApplicationState, errors::AppError> {
|
) -> Result<CentralState, errors::AppError> {
|
||||||
let state = app_state.read().await;
|
let state = app_state.read().await;
|
||||||
let mut peripherals: Vec<PeripheralItem> = vec![];
|
|
||||||
let mut connected_peripheral = None;
|
|
||||||
|
|
||||||
let central = state.get_central_adapter().await;
|
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
|
let central_device_state = central
|
||||||
.adapter_state()
|
.adapter_state()
|
||||||
.await
|
.await
|
||||||
.map_err(|_| errors::AppError::BluetoothNotReady)?;
|
.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
|
let found_peripherals = central
|
||||||
.peripherals()
|
.peripherals()
|
||||||
.await
|
.await
|
||||||
|
@ -69,38 +122,25 @@ pub async fn refresh_application_state(
|
||||||
rssi: properties.rssi,
|
rssi: properties.rssi,
|
||||||
battery: properties.tx_power_level,
|
battery: properties.tx_power_level,
|
||||||
};
|
};
|
||||||
if peripheral
|
|
||||||
.is_connected()
|
|
||||||
.await
|
|
||||||
.map_err(|_| errors::AppError::UnableToRetrievePeripheralState)?
|
|
||||||
{
|
|
||||||
connected_peripheral = Some(item.clone());
|
|
||||||
}
|
|
||||||
peripherals.push(item);
|
peripherals.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
Ok(peripherals)
|
||||||
|
}
|
||||||
|
|
||||||
CentralState {
|
#[tauri::command]
|
||||||
is_ready: central_device_state == btleplug::api::CentralState::PoweredOn,
|
pub async fn channel_a_state(
|
||||||
is_scanning: *state.scanning.lock().await,
|
_app_state: State<'_, Arc<RwLock<AppState>>>,
|
||||||
connected: state
|
) -> Result<ChannelState, errors::AppError> {
|
||||||
.connected_peripheral
|
Ok(ChannelState::default())
|
||||||
.lock()
|
}
|
||||||
.await
|
|
||||||
.clone()
|
|
||||||
.map(|p| p.id()),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
CentralState::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(ApplicationState {
|
#[tauri::command]
|
||||||
central: central_state,
|
pub async fn channel_b_state(
|
||||||
peripherals,
|
_app_state: State<'_, Arc<RwLock<AppState>>>,
|
||||||
connected_peripheral,
|
) -> Result<ChannelState, errors::AppError> {
|
||||||
channel_a: ChannelState::default(),
|
Ok(ChannelState::default())
|
||||||
channel_b: ChannelState::default(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
|
|
@ -4,6 +4,7 @@ use serde::Serialize;
|
||||||
use crate::playlist::PlayMode;
|
use crate::playlist::PlayMode;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize)]
|
#[derive(Debug, Clone, Default, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CentralState {
|
pub struct CentralState {
|
||||||
pub is_ready: bool,
|
pub is_ready: bool,
|
||||||
pub is_scanning: bool,
|
pub is_scanning: bool,
|
||||||
|
@ -11,6 +12,7 @@ pub struct CentralState {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct PeripheralItem {
|
pub struct PeripheralItem {
|
||||||
pub id: PeripheralId,
|
pub id: PeripheralId,
|
||||||
pub address: String,
|
pub address: String,
|
||||||
|
@ -21,6 +23,7 @@ pub struct PeripheralItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize)]
|
#[derive(Debug, Clone, Default, Serialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ChannelState {
|
pub struct ChannelState {
|
||||||
pub is_playing: bool,
|
pub is_playing: bool,
|
||||||
pub strength: u32,
|
pub strength: u32,
|
||||||
|
@ -30,12 +33,3 @@ pub struct ChannelState {
|
||||||
pub boost_limit: u32,
|
pub boost_limit: u32,
|
||||||
pub play_mode: PlayMode,
|
pub play_mode: PlayMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize)]
|
|
||||||
pub struct ApplicationState {
|
|
||||||
pub central: CentralState,
|
|
||||||
pub peripherals: Vec<PeripheralItem>,
|
|
||||||
pub connected_peripheral: Option<PeripheralItem>,
|
|
||||||
pub channel_a: ChannelState,
|
|
||||||
pub channel_b: ChannelState,
|
|
||||||
}
|
|
||||||
|
|
|
@ -53,7 +53,11 @@ pub fn run() {
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.invoke_handler(generate_handler![
|
.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::activate_central_adapter,
|
||||||
cmd::start_scan_devices,
|
cmd::start_scan_devices,
|
||||||
cmd::stop_scan_devices
|
cmd::stop_scan_devices
|
||||||
|
|
Loading…
Reference in New Issue
Block a user