diff --git a/src/connections/ble_handler.rs b/src/connections/ble_handler.rs index 074d716..df78203 100644 --- a/src/connections/ble_handler.rs +++ b/src/connections/ble_handler.rs @@ -1,6 +1,6 @@ use btleplug::api::{ - Central, Characteristic, Manager as _, Peripheral as _, ScanFilter, ValueNotification, - WriteType, + Central, CentralEvent, Characteristic, Manager as _, Peripheral as _, ScanFilter, + ValueNotification, WriteType, }; use btleplug::platform::{Adapter, Manager, Peripheral}; use futures_util::stream::BoxStream; @@ -16,6 +16,7 @@ const FROMNUM: Uuid = Uuid::from_u128(0xed9da18c_a800_4f66_a670_aa7547e34453); pub struct BleHandler { radio: Peripheral, + adapter: Adapter, toradio_char: Characteristic, fromradio_char: Characteristic, fromnum_char: Characteristic, @@ -24,7 +25,7 @@ pub struct BleHandler { #[allow(dead_code)] impl BleHandler { pub async fn new(name: String) -> Result { - let radio = Self::find_ble_radio(&name).await?; + let (radio, adapter) = Self::find_ble_radio(&name).await?; radio.connect().await.map_err(|e| Error::StreamBuildError { source: Box::new(e), description: format!("Failed to connect to the device {name}"), @@ -33,6 +34,7 @@ impl BleHandler { Self::find_characteristics(&radio).await?; Ok(BleHandler { radio, + adapter, toradio_char, fromradio_char, fromnum_char, @@ -50,7 +52,9 @@ impl BleHandler { /// Finds a BLE radio matching a given name and running meshtastic. /// It searches for the 'MSH_SERVICE' running on the device. - async fn find_ble_radio(name: &str) -> Result { + /// + /// It also returns the associated adapter that can reach this radio. + async fn find_ble_radio(name: &str) -> Result<(Peripheral, Adapter), Error> { //TODO: support searching both by a name and by a MAC address let scan_error_fn = |e: btleplug::Error| Error::StreamBuildError { source: Box::new(e), @@ -72,7 +76,7 @@ impl BleHandler { for peripheral in peripherals { if let Ok(Some(peripheral_properties)) = peripheral.properties().await { if peripheral_properties.local_name == needle { - return Ok(peripheral); + return Ok((peripheral, adapter.clone())); } } } @@ -178,4 +182,21 @@ impl BleHandler { _ => None, } } + + pub async fn adapter_events(&self) -> Result, Error> { + self.adapter + .events() + .await + .map_err(|e| Error::StreamBuildError { + source: Box::new(e), + description: format!("Failed to listen to device events"), + }) + } + + pub fn is_disconnected_event(&self, event: Option) -> bool { + if let Some(CentralEvent::DeviceDisconnected(peripheral_id)) = event { + return self.radio.id() == peripheral_id; + } + return false; + } } diff --git a/src/errors_internal.rs b/src/errors_internal.rs index 4fab3c8..f44719b 100644 --- a/src/errors_internal.rs +++ b/src/errors_internal.rs @@ -67,6 +67,11 @@ pub enum InternalStreamError { StreamWriteError { source: Box, }, + + /// An error indicatiing that the connection has been lost and both reading and writing are + /// not possible anymore. + #[error("Connection lost")] + ConnectionLost, } /// An enum that defines the possible internal errors that can occur within the library when handling data channels.