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 <noreply@anthropic.com>
This commit is contained in:
sl-ios 2026-04-06 15:20:30 -04:00
parent c472668d7a
commit 7b911d3591

View File

@ -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