From 7b911d3591cf46baf2afc380c6ec21950c38047d Mon Sep 17 00:00:00 2001 From: sl-ios Date: Mon, 6 Apr 2026 15:20:30 -0400 Subject: [PATCH] fix: scan all peripherals so NimBLE service UUID in scan response is not missed iOS CoreBluetooth only fires didDiscover when the service UUID is in the primary ADV_IND packet. NimBLE (ESP32) puts service UUIDs in the scan response by default, so scanForPeripherals(withServices:[uuid]) never returned the UWB_TAG device. Fix: scan with withServices:nil and filter by device name prefix "UWB_TAG" in didDiscover. Also fix the broken OR guard (|| name.isEmpty == false passed any named peripheral) to a clean hasPrefix check. Co-Authored-By: Claude Sonnet 4.6 --- SulTee/SulTee/BLEManager.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/SulTee/SulTee/BLEManager.swift b/SulTee/SulTee/BLEManager.swift index 376cd7c..d468576 100644 --- a/SulTee/SulTee/BLEManager.swift +++ b/SulTee/SulTee/BLEManager.swift @@ -82,7 +82,11 @@ final class BLEManager: NSObject, ObservableObject { private func doStartScan() { DispatchQueue.main.async { self.connectionState = .scanning } - central.scanForPeripherals(withServices: [Self.serviceUUID], + // Scan for ALL peripherals — NimBLE (ESP32) puts service UUIDs in the scan + // response, not the primary advertisement. iOS won't call didDiscover for + // service-filtered scans unless the UUID is in the primary ADV_IND packet. + // We filter by device name prefix in didDiscover instead. + central.scanForPeripherals(withServices: nil, options: [CBCentralManagerScanOptionAllowDuplicatesKey: false]) // Auto-stop after 15 s if nothing found scanTimer?.invalidate() @@ -122,9 +126,8 @@ extension BLEManager: CBCentralManagerDelegate { didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) { - // Match by service advertisement or device name prefix - let name = peripheral.name ?? "" - guard name.hasPrefix("UWB_TAG") || name.isEmpty == false else { return } + // Only connect to UWB_TAG devices (name prefix set by NimBLE on tag firmware) + guard let name = peripheral.name, name.hasPrefix("UWB_TAG") else { return } stopScan() self.peripheral = peripheral peripheral.delegate = self