fix: use dedicated retry counter for device info disconnect

The device info disconnect handler was sharing connectionRetryCount with
the initial connection retry logic. If earlier connection attempts burned
through retries, the device info handler had zero retries left and
immediately hit "retries exhausted" — causing the "Disconnected while
reading device information" error John reported.

Now uses a separate deviceInfoRetryCount (max 2) so device info retries
are independent of connection retries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Schwifty 2026-03-21 23:35:15 +00:00
parent 3d56a1e31d
commit 64e3684209

View file

@ -178,7 +178,9 @@ class BeaconProvisioner: NSObject, ObservableObject {
// Connection retry state
private var connectionRetryCount = 0
private var deviceInfoRetryCount = 0
private static let MAX_CONNECTION_RETRIES = 3
private static let MAX_DEVICE_INFO_RETRIES = 2
private var currentBeacon: DiscoveredBeacon?
override init() {
@ -219,6 +221,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
self.skipDeviceInfoRead = false
self.isTerminating = false
self.connectionRetryCount = 0
self.deviceInfoRetryCount = 0
self.currentBeacon = beacon
state = .connecting
@ -266,6 +269,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
self.dxReadQueryIndex = 0
self.allDiscoveredServices.removeAll()
self.connectionRetryCount = 0
self.deviceInfoRetryCount = 0
self.isTerminating = false
self.currentBeacon = beacon
self.servicesToExplore.removeAll()
@ -303,6 +307,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
skipDeviceInfoRead = false
isTerminating = false
connectionRetryCount = 0
deviceInfoRetryCount = 0
currentBeacon = nil
state = .idle
progress = ""
@ -905,6 +910,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
configService = nil
characteristics.removeAll()
connectionRetryCount = 0
deviceInfoRetryCount = 0
currentBeacon = nil
operationMode = .provisioning
state = .idle
@ -1030,11 +1036,11 @@ extension BeaconProvisioner: CBCentralManagerDelegate {
awaitingDeviceInfoForProvisioning = false
skipDeviceInfoRead = true // on reconnect, go straight to config write
if connectionRetryCount < BeaconProvisioner.MAX_CONNECTION_RETRIES {
connectionRetryCount += 1
let delay = Double(connectionRetryCount)
if deviceInfoRetryCount < BeaconProvisioner.MAX_DEVICE_INFO_RETRIES {
deviceInfoRetryCount += 1
let delay = Double(deviceInfoRetryCount)
progress = "Reconnecting (skip MAC read)..."
DebugLog.shared.log("BLE: Disconnect during device info read — reconnecting (\(connectionRetryCount)/\(BeaconProvisioner.MAX_CONNECTION_RETRIES)), will skip MAC read")
DebugLog.shared.log("BLE: Disconnect during device info read — reconnecting (\(deviceInfoRetryCount)/\(BeaconProvisioner.MAX_DEVICE_INFO_RETRIES)), will skip MAC read")
// Reset BLE state for reconnect
dxSmartAuthenticated = false
@ -1056,7 +1062,7 @@ extension BeaconProvisioner: CBCentralManagerDelegate {
}
return
} else {
DebugLog.shared.log("BLE: Disconnect during device info read — max retries exhausted")
DebugLog.shared.log("BLE: Disconnect during device info read — max device info retries exhausted (\(deviceInfoRetryCount)/\(BeaconProvisioner.MAX_DEVICE_INFO_RETRIES))")
fail("Disconnected while reading device information (retries exhausted)", code: .disconnected)
return
}