Skip to content

Commit

Permalink
feat: add DisconnectAll command in async bridge and refactor StateRes…
Browse files Browse the repository at this point in the history
…ponse
  • Loading branch information
gmallios committed Mar 20, 2024
1 parent 20dc538 commit 165045d
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 24 deletions.
47 changes: 32 additions & 15 deletions manager-app/src/async_bridge/bridge.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::sync::Arc;

use log::debug;
use log::{debug, info, trace};
use tauri::AppHandle;
use tokio::sync::{mpsc, Mutex};

Expand All @@ -10,17 +10,15 @@ use soundcore_lib::{
device_manager::{create_device_manager, DeviceManager},
};

use super::{BridgeCommand, BridgeResponse, NewStateResponse};
use super::{BridgeCommand, BridgeResponse, TaggedStateResponse};

struct CommandLoopState<B: BLEConnectionManager> {
manager: DeviceManager<B>,
}

impl<B: BLEConnectionManager> CommandLoopState<B> {
fn new(manager: DeviceManager<B>) -> Self {
Self {
manager,
}
Self { manager }
}
}

Expand All @@ -29,8 +27,7 @@ pub async fn async_bridge(
output_tx: mpsc::Sender<BridgeResponse>,
) {
tokio::spawn(async move {
let manager =
create_device_manager().await;
let manager = create_device_manager().await;

// Adapter events
let mut manager_event_channel = manager.get_event_channel().await.unwrap();
Expand Down Expand Up @@ -82,27 +79,47 @@ async fn handle_command<B: BLEConnectionManager>(
.await
.map(|_| BridgeResponse::Disconnected(addr_clone))
}
BridgeCommand::DisconnectAll => {
command_loop_state
.lock()
.await
.manager
.disconnect_all()
.await.map(|_| BridgeResponse::DisconnectedAll)
}
BridgeCommand::Connect(d) => {
let addr = d.clone().descriptor.addr;
let device = command_loop_state.lock().await.manager.connect(d).await;
let addr_clone = addr.clone();
if let Ok(device) = device {
// Get the state channel and listen for changes in the background
let mut state_channel = device.state_channel().await;
tokio::task::spawn(async move {
let _ = tokio::task::spawn(async move {
info!("Listening for state changes for {:?}", addr_clone);
while let Ok(()) = state_channel.changed().await {
let state = state_channel.borrow().clone();
// TODO: Add logging
let new_state_response = NewStateResponse {
addr: addr_clone.clone(),
trace!(
"Got new state {:?} for {:?}, sending event...",
state,
};
output_tx
.send(BridgeResponse::NewState(new_state_response))
addr_clone
);
let res = output_tx
.send(BridgeResponse::NewState(TaggedStateResponse {
addr: addr_clone.clone(),
state,
}))
.await;

if let Err(e) = res {
debug!("Failed to send new state event: {:?}", e);
}
}
trace!("State channel for {:?} closed", addr_clone);
});
Ok(BridgeResponse::ConnectionEstablished(addr))
Ok(BridgeResponse::ConnectionEstablished(TaggedStateResponse {
addr,
state: device.latest_state().await,
}))
} else {
Err(device.err().unwrap())
}
Expand Down
1 change: 1 addition & 0 deletions manager-app/src/async_bridge/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ pub enum BridgeCommand {
Scan,
Connect(DiscoveredDevice),
Disconnect(BluetoothAdrr),
DisconnectAll,
}
7 changes: 4 additions & 3 deletions manager-app/src/async_bridge/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@ use typeshare::typeshare;
#[typeshare]
pub enum BridgeResponse {
ScanResult(Vec<DiscoveredDevice>),
ConnectionEstablished(BluetoothAdrr),
NewState(NewStateResponse),
ConnectionEstablished(TaggedStateResponse),
NewState(TaggedStateResponse),
Disconnected(BluetoothAdrr),
DisconnectedAll,
AdapterEvent(BLEAdapterEvent),
Error(String),
}

#[derive(Debug, Serialize, Clone)]
#[serde(rename_all = "camelCase")]
#[typeshare]
pub struct NewStateResponse {
pub struct TaggedStateResponse {
pub addr: BluetoothAdrr,
pub state: SoundcoreDeviceState,
}
10 changes: 6 additions & 4 deletions manager-ui/src/types/tauri-backend.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Generated by typeshare 1.7.0
*/

export interface NewStateResponse {
export interface TaggedStateResponse {
addr: BluetoothAdrr;
state: SoundcoreDeviceState;
}
Expand Down Expand Up @@ -46,12 +46,14 @@ export interface DeviceFeatures {
export type BridgeCommand =
| { command: 'scan'; payload?: undefined }
| { command: 'connect'; payload: DiscoveredDevice }
| { command: 'disconnect'; payload: BluetoothAdrr };
| { command: 'disconnect'; payload: BluetoothAdrr }
| { command: 'disconnectAll'; payload?: undefined };

export type BridgeResponse =
| { kind: 'scanResult'; payload: DiscoveredDevice[] }
| { kind: 'connectionEstablished'; payload: BluetoothAdrr }
| { kind: 'newState'; payload: NewStateResponse }
| { kind: 'connectionEstablished'; payload: TaggedStateResponse }
| { kind: 'newState'; payload: TaggedStateResponse }
| { kind: 'disconnected'; payload: BluetoothAdrr }
| { kind: 'disconnectedAll'; payload?: undefined }
| { kind: 'adapterEvent'; payload: BLEAdapterEvent }
| { kind: 'error'; payload: string };
11 changes: 9 additions & 2 deletions soundcore-lib/src/device_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,18 @@ where
.collect::<Vec<_>>())
}

pub async fn get_event_channel(&self) -> SoundcoreLibResult<tokio::sync::mpsc::Receiver<BLEAdapterEvent>> {
pub async fn get_event_channel(
&self,
) -> SoundcoreLibResult<tokio::sync::mpsc::Receiver<BLEAdapterEvent>> {
self.ble_manager.adapter_events().await
}

pub async fn disconnect_all(&self) -> SoundcoreLibResult<()> {
let mut devices = self.ble_devices.write().await;
devices.clear();
Ok(())
}

fn map_descriptor_to_discovered_device(descriptor: &BLEDeviceDescriptor) -> DiscoveredDevice {
DiscoveredDevice {
descriptor: descriptor.to_owned(),
Expand All @@ -103,7 +111,6 @@ where
None => discovered_device,
}
}

}

/// A discovered BLE device. The DiscoveredDevice can be upgraded to a SoundcoreBLEDevice.
Expand Down

0 comments on commit 165045d

Please sign in to comment.