From a02fb9588e169f33a309a3e445e6eace0096ee89 Mon Sep 17 00:00:00 2001 From: Ansgar Prause Date: Wed, 5 Jul 2023 23:11:54 +0200 Subject: [PATCH 1/3] Recreate client on reconnect Co-authored-by: Marcus Weiner --- src/client.rs | 49 ++++++++++++++++++++++++------------------------ src/keyturner.rs | 2 +- src/main.rs | 12 ++++++++++-- src/pairing.rs | 2 +- 4 files changed, 37 insertions(+), 28 deletions(-) diff --git a/src/client.rs b/src/client.rs index 43e0ebc..f65433f 100644 --- a/src/client.rs +++ b/src/client.rs @@ -1,6 +1,6 @@ use anyhow::anyhow; -use bluest::{Adapter, Characteristic, Device}; +use bluest::{Adapter, Characteristic, Device, DeviceId}; use futures_util::StreamExt; use std::{future::Future, sync::Arc}; use tokio::sync::mpsc; @@ -14,8 +14,9 @@ pub struct Client { device: Device, } -pub struct UnconnectedClient { - name: String, +pub enum UnconnectedClient { + Name(String), + DeviceId(DeviceId), } pub struct CharacteristicClient { @@ -27,7 +28,11 @@ pub struct CharacteristicClient { impl UnconnectedClient { pub fn new(name: String) -> Self { - Self { name } + Self::Name(name) + } + + pub fn with_id(device_id: DeviceId) -> Self { + Self::DeviceId(device_id) } pub async fn connect(self) -> Result { @@ -53,6 +58,13 @@ impl UnconnectedClient { } async fn discover_device(&self, adapter: &Adapter) -> Result { + let name = match &self { + Self::Name(name) => name, + Self::DeviceId(device_id) => { + return adapter.open_device(&device_id).await.map_err(Into::into) + } + }; + info!("starting scan"); let mut scan = adapter.scan(&[]).await?; info!("scan started"); @@ -72,7 +84,7 @@ impl UnconnectedClient { .device .name() .as_deref() - .map(|name| name == self.name) + .map(|n| n == name) .unwrap_or(false) { return Ok(discovered_device.device); @@ -83,22 +95,15 @@ impl UnconnectedClient { } } -async fn retry(limit: usize, mut f: F) -> Result -where - F: FnMut() -> Fut, - Fut: Future>, - E: std::error::Error, -{ - for _ in 0..limit { - match f().await { - Ok(r) => return Ok(r), - Err(e) => eprintln!("Retrying after error: {:?}", e), - } +impl Client { + pub async fn is_connected(&self) -> bool { + self.device.is_connected().await + } + + pub fn device_id(&self) -> DeviceId { + self.device.id() } - Err(anyhow!("Retry limit reached")) -} -impl Client { pub async fn with_characteristic( &self, service_id: &str, @@ -158,11 +163,7 @@ impl CharacteristicClient { pub async fn write_raw(&self, bytes: impl AsRef<[u8]>) -> Result<(), anyhow::Error> { if !self.device.is_connected().await { - retry(5, || { - debug!("Connecting to device"); - self.adapter.connect_device(&self.device) - }) - .await?; + return Err(anyhow!("Device not connected")); } self.characteristic.write(bytes.as_ref()).await?; diff --git a/src/keyturner.rs b/src/keyturner.rs index 229b793..969415d 100644 --- a/src/keyturner.rs +++ b/src/keyturner.rs @@ -19,7 +19,7 @@ pub struct Keyturner { } impl Keyturner { - pub async fn new(auth_info: AuthInfo, client: Client) -> Result { + pub async fn new(auth_info: AuthInfo, client: &Client) -> Result { let characteristic = client .with_characteristic(KEY_TURNER_SERVICE, KEY_TURNER_USDIO) .await?; diff --git a/src/main.rs b/src/main.rs index b0cb033..56b3e10 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,15 +42,23 @@ async fn main() -> Result<(), anyhow::Error> { let stream = nfc_stream::run().unwrap(); tokio::pin!(stream); - let connected_client = UnconnectedClient::new(LOCK_NAME.into()).connect().await?; + let mut connected_client = UnconnectedClient::new(LOCK_NAME.into()).connect().await?; let auth_info = AuthInfo::read_from_file("auth-info.json").await?; - let mut keyturner = Keyturner::new(auth_info, connected_client).await?; + let mut keyturner = Keyturner::new(auth_info.clone(), &connected_client).await?; loop { let item = stream.next().await; + if !connected_client.is_connected().await { + info!("Reconnecting client"); + connected_client = UnconnectedClient::with_id(connected_client.device_id()) + .connect() + .await?; + keyturner = Keyturner::new(auth_info.clone(), &connected_client).await?; + } + info!("{:?}", item); let Some(item) = item else { diff --git a/src/pairing.rs b/src/pairing.rs index 2641790..512ed3b 100644 --- a/src/pairing.rs +++ b/src/pairing.rs @@ -30,7 +30,7 @@ pub struct PairingClient { base64_serde_type!(Base64Serde, STANDARD); -#[derive(Serialize, Deserialize)] +#[derive(Clone, Debug, Serialize, Deserialize)] pub struct AuthInfo { pub authorization_id: u32, #[serde(serialize_with = "serialize_key", deserialize_with = "deserialize_key")] From 00ab939a21f9d11638b7e0ac065ad25a6ce76711 Mon Sep 17 00:00:00 2001 From: Ansgar Prause Date: Wed, 5 Jul 2023 23:12:57 +0200 Subject: [PATCH 2/3] Fix clippy --- src/client.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/client.rs b/src/client.rs index f65433f..3e69728 100644 --- a/src/client.rs +++ b/src/client.rs @@ -2,7 +2,7 @@ use anyhow::anyhow; use bluest::{Adapter, Characteristic, Device, DeviceId}; use futures_util::StreamExt; -use std::{future::Future, sync::Arc}; +use std::sync::Arc; use tokio::sync::mpsc; use tracing::{debug, info, warn}; @@ -20,7 +20,7 @@ pub enum UnconnectedClient { } pub struct CharacteristicClient { - adapter: Arc, + _adapter: Arc, responses: mpsc::Receiver>, characteristic: Arc, device: Device, @@ -148,7 +148,7 @@ impl Client { }); Ok(CharacteristicClient { - adapter: Arc::clone(&self.adapter), + _adapter: Arc::clone(&self.adapter), characteristic, device: self.device.clone(), responses: rx, From 4943906abde7dce22c579d4da3b339c58312c39e Mon Sep 17 00:00:00 2001 From: Ansgar Prause Date: Wed, 5 Jul 2023 23:18:20 +0200 Subject: [PATCH 3/3] Fix clippy --- src/client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.rs b/src/client.rs index 3e69728..1976f61 100644 --- a/src/client.rs +++ b/src/client.rs @@ -61,7 +61,7 @@ impl UnconnectedClient { let name = match &self { Self::Name(name) => name, Self::DeviceId(device_id) => { - return adapter.open_device(&device_id).await.map_err(Into::into) + return adapter.open_device(device_id).await.map_err(Into::into) } };