From fd0e323f022e8634a5b9f446292c55c71246d638 Mon Sep 17 00:00:00 2001 From: Akrm Al-Hakimi Date: Mon, 2 Mar 2026 21:02:24 -0500 Subject: [PATCH] refactor(#223): convert bdaddr into bluez dbus object path --- nmrs/CHANGELOG.md | 2 ++ nmrs/src/core/bluetooth.rs | 36 +++++++++++++++--------------------- nmrs/src/util/utils.rs | 9 +++++++++ 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/nmrs/CHANGELOG.md b/nmrs/CHANGELOG.md index 93021fe0..9d9a0927 100644 --- a/nmrs/CHANGELOG.md +++ b/nmrs/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to the `nmrs` crate will be documented in this file. ## [Unreleased] +### Changed +- Convert BDADDR to BlueZ device path via `bluez_device_path` helper ([#266](https://github.com/cachebag/nmrs/pull/266)) ## [2.1.0] - 2026-02-28 ### Added diff --git a/nmrs/src/core/bluetooth.rs b/nmrs/src/core/bluetooth.rs index 0b6c77d3..676dc393 100644 --- a/nmrs/src/core/bluetooth.rs +++ b/nmrs/src/core/bluetooth.rs @@ -19,6 +19,7 @@ use crate::monitoring::bluetooth::Bluetooth; use crate::monitoring::transport::ActiveTransport; use crate::types::constants::device_state; use crate::types::constants::device_type; +use crate::util::utils::bluez_device_path; use crate::util::validation::validate_bluetooth_address; use crate::ConnectionError; use crate::{ @@ -45,10 +46,7 @@ pub(crate) async fn populate_bluez_info( ) -> Result<(Option, Option)> { validate_bluetooth_address(bdaddr)?; - // [variable prefix]/{hci0,hci1,...}/dev_XX_XX_XX_XX_XX_XX - // This replaces ':' with '_' in the BDADDR to form the correct D-Bus object path. - // TODO: Instead of hardcoding hci0, we should determine the actual adapter name. - let bluez_path = format!("/org/bluez/hci0/dev_{}", bdaddr.replace(':', "_")); + let bluez_path = bluez_device_path(bdaddr); match BluezDeviceExtProxy::builder(conn) .path(bluez_path)? @@ -144,14 +142,8 @@ pub(crate) async fn connect_bluetooth( // Check for saved connection let saved = get_saved_connection_path(conn, name).await?; - // For Bluetooth, the "specific_object" is the remote device's D-Bus path - // Format: /org/bluez/hci0/dev_XX_XX_XX_XX_XX_XX - // TODO: Instead of hardcoding the hci0, we should use the actual hardware adapter name. - let specific_object = OwnedObjectPath::try_from(format!( - "/org/bluez/hci0/dev_{}", - settings.bdaddr.replace(':', "_") - )) - .map_err(|e| ConnectionError::InvalidAddress(format!("Invalid BlueZ path: {}", e)))?; + let specific_object = OwnedObjectPath::try_from(bluez_device_path(&settings.bdaddr)) + .map_err(|e| ConnectionError::InvalidAddress(format!("Invalid BlueZ path: {e}")))?; match saved { Some(saved_path) => { @@ -247,24 +239,26 @@ mod tests { #[test] fn test_bluez_path_format() { - // Test that bdaddr format is converted correctly for D-Bus path - let bdaddr = "00:1A:7D:DA:71:13"; - let expected_path = "/org/bluez/hci0/dev_00_1A_7D_DA_71_13"; - let actual_path = format!("/org/bluez/hci0/dev_{}", bdaddr.replace(':', "_")); - assert_eq!(actual_path, expected_path); + assert_eq!( + bluez_device_path("00:1A:7D:DA:71:13"), + "/org/bluez/hci0/dev_00_1A_7D_DA_71_13" + ); } #[test] fn test_bluez_path_format_various_addresses() { - let test_cases = vec![ + let test_cases = [ ("AA:BB:CC:DD:EE:FF", "/org/bluez/hci0/dev_AA_BB_CC_DD_EE_FF"), ("00:00:00:00:00:00", "/org/bluez/hci0/dev_00_00_00_00_00_00"), ("C8:1F:E8:F0:51:57", "/org/bluez/hci0/dev_C8_1F_E8_F0_51_57"), ]; - for (bdaddr, expected_path) in test_cases { - let actual_path = format!("/org/bluez/hci0/dev_{}", bdaddr.replace(':', "_")); - assert_eq!(actual_path, expected_path, "Failed for bdaddr: {}", bdaddr); + for (bdaddr, expected) in test_cases { + assert_eq!( + bluez_device_path(bdaddr), + expected, + "Failed for bdaddr: {bdaddr}" + ); } } diff --git a/nmrs/src/util/utils.rs b/nmrs/src/util/utils.rs index 0d8744af..c1e6e601 100644 --- a/nmrs/src/util/utils.rs +++ b/nmrs/src/util/utils.rs @@ -239,6 +239,15 @@ pub(crate) async fn extract_connection_state_reason( } } +/// Constructs a BlueZ D-Bus object path from a Bluetooth device address. +/// +/// Converts a BDADDR like `"00:1A:7D:DA:71:13"` into +/// `"/org/bluez/hci0/dev_00_1A_7D_DA_71_13"`. +// TODO: Instead of hardcoding hci0, determine the actual adapter name. +pub(crate) fn bluez_device_path(bdaddr: &str) -> String { + format!("/org/bluez/hci0/dev_{}", bdaddr.replace(':', "_")) +} + /// Macro to convert Result to Option with error logging. /// Usage: `try_log!(result, "context message")?` #[macro_export]