From 10303b3fa71286b65779ba3e4534695e0250a2fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Filistovi=C4=8D?= Date: Tue, 28 Jul 2026 10:17:40 +0300 Subject: [PATCH] [ble_device_base] Add mac_lsb_first_to_uint64 address-packing helper (#17901) --- esphome/components/ble_device_base/ble_device.h | 14 ++++++++++++++ tests/components/ble_device_base/test_address.cpp | 15 +++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/esphome/components/ble_device_base/ble_device.h b/esphome/components/ble_device_base/ble_device.h index 94678091cc..2d2cb5796b 100644 --- a/esphome/components/ble_device_base/ble_device.h +++ b/esphome/components/ble_device_base/ble_device.h @@ -144,6 +144,20 @@ class ESPBLEiBeacon { } beacon_data_; }; +/// Pack a controller-order (LSB-first) MAC into the uint64 the API speaks. +/// +/// The result is the printable-order value esp32 has always sent +/// (esp32_ble::ble_addr_to_uint64), so both proxy paths agree on the wire. +/// This takes the raw controller order delivered by BLEHub's raw-advertisement +/// callback; ESPBTDevice::address_uint64() is the equivalent for an already +/// parsed device, whose address is stored MSB-first. +inline uint64_t mac_lsb_first_to_uint64(const uint8_t *mac) { + uint64_t addr = 0; + for (int i = 0; i < 6; i++) + addr |= static_cast(mac[i]) << (i * 8); + return addr; +} + // --------------------------------------------------------------------------- // ESPBTDevice — parsed BLE advertisement // --------------------------------------------------------------------------- diff --git a/tests/components/ble_device_base/test_address.cpp b/tests/components/ble_device_base/test_address.cpp index c903003a7c..9e4bca4c57 100644 --- a/tests/components/ble_device_base/test_address.cpp +++ b/tests/components/ble_device_base/test_address.cpp @@ -28,4 +28,19 @@ TEST(BleDeviceAddress, AccessorsMatchEsp32Semantics) { EXPECT_EQ(device.address_str(), "AA:BB:CC:DD:EE:FF"); } +// mac_lsb_first_to_uint64() packs the controller-order bytes a raw-advertisement +// callback delivers into the printable-order uint64 the native API speaks — the +// value esp32_ble::ble_addr_to_uint64() has always produced for that address. +TEST(BleDeviceAddress, MacLsbFirstToUint64MatchesWireValue) { + EXPECT_EQ(mac_lsb_first_to_uint64(MAC_LSB_FIRST), 0xAABBCCDDEEFFULL); +} + +// The helper and the parsed-device accessor are two routes to the same wire +// value: byte order must agree no matter which path an advertisement takes. +TEST(BleDeviceAddress, MacLsbFirstToUint64AgreesWithParsedDevice) { + ESPBTDevice device; + device.from_scan_result(MAC_LSB_FIRST, -50, BLE_ADDR_TYPE_PUBLIC, nullptr, 0); + EXPECT_EQ(mac_lsb_first_to_uint64(MAC_LSB_FIRST), device.address_uint64()); +} + } // namespace esphome::ble_device_base::testing