fix: increase pre-auth delay to 2s and add one-shot reconnect on auth disconnect
- PRE_AUTH_DELAY bumped from 0.8s to 2.0s — beacons need more stabilization time after characteristic discovery before password write - If disconnect happens during authenticating state, retry connection once with full re-discovery instead of immediate failure - Reset authDisconnectRetried flag on new provision and cleanup
This commit is contained in:
parent
972291e93b
commit
fc13986396
1 changed files with 24 additions and 1 deletions
|
|
@ -160,6 +160,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
private var dxSmartWriteIndex = 0
|
private var dxSmartWriteIndex = 0
|
||||||
private var provisioningMacAddress: String?
|
private var provisioningMacAddress: String?
|
||||||
private var isTerminating = false // guards against re-entrant disconnect handling
|
private var isTerminating = false // guards against re-entrant disconnect handling
|
||||||
|
private var authDisconnectRetried = false // one-shot retry if disconnect during auth
|
||||||
|
|
||||||
// Read config mode
|
// Read config mode
|
||||||
private enum OperationMode { case provisioning, readingConfig }
|
private enum OperationMode { case provisioning, readingConfig }
|
||||||
|
|
@ -198,7 +199,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
// Prevention > recovery: generous delays prevent supervision timeouts.
|
// Prevention > recovery: generous delays prevent supervision timeouts.
|
||||||
private static let INTER_COMMAND_DELAY: Double = 0.5
|
private static let INTER_COMMAND_DELAY: Double = 0.5
|
||||||
private static let HEAVY_COMMAND_DELAY: Double = 1.0 // After frame select/type changes
|
private static let HEAVY_COMMAND_DELAY: Double = 1.0 // After frame select/type changes
|
||||||
private static let PRE_AUTH_DELAY: Double = 0.8 // After discovery, before first auth write
|
private static let PRE_AUTH_DELAY: Double = 2.0 // After discovery, before first auth write (0.8 was too short — beacons drop connection)
|
||||||
private static let POST_AUTH_DELAY: Double = 1.5 // After auth, before first write
|
private static let POST_AUTH_DELAY: Double = 1.5 // After auth, before first write
|
||||||
|
|
||||||
// Readiness gate — don't start writing until we've confirmed all 3 chars
|
// Readiness gate — don't start writing until we've confirmed all 3 chars
|
||||||
|
|
@ -238,6 +239,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
self.dxSmartWriteIndex = 0
|
self.dxSmartWriteIndex = 0
|
||||||
self.provisioningMacAddress = nil
|
self.provisioningMacAddress = nil
|
||||||
self.isTerminating = false
|
self.isTerminating = false
|
||||||
|
self.authDisconnectRetried = false
|
||||||
self.awaitingCommandResponse = false
|
self.awaitingCommandResponse = false
|
||||||
self.requiredCharsConfirmed = false
|
self.requiredCharsConfirmed = false
|
||||||
cancelResponseGateTimeout()
|
cancelResponseGateTimeout()
|
||||||
|
|
@ -328,6 +330,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
|
||||||
dxSmartWriteIndex = 0
|
dxSmartWriteIndex = 0
|
||||||
provisioningMacAddress = nil
|
provisioningMacAddress = nil
|
||||||
isTerminating = false
|
isTerminating = false
|
||||||
|
authDisconnectRetried = false
|
||||||
requiredCharsConfirmed = false
|
requiredCharsConfirmed = false
|
||||||
connectionRetryCount = 0
|
connectionRetryCount = 0
|
||||||
currentBeacon = nil
|
currentBeacon = nil
|
||||||
|
|
@ -1077,6 +1080,26 @@ extension BeaconProvisioner: CBCentralManagerDelegate {
|
||||||
cancelResponseGateTimeout()
|
cancelResponseGateTimeout()
|
||||||
awaitingCommandResponse = false
|
awaitingCommandResponse = false
|
||||||
|
|
||||||
|
// If we disconnect during authentication and haven't retried yet,
|
||||||
|
// reconnect once — the beacon may just need a fresh connection with more settling time.
|
||||||
|
if state == .authenticating && !authDisconnectRetried {
|
||||||
|
authDisconnectRetried = true
|
||||||
|
DebugLog.shared.log("BLE: Disconnect during auth — retrying connection once")
|
||||||
|
progress = "Reconnecting..."
|
||||||
|
state = .connecting
|
||||||
|
passwordIndex = 0
|
||||||
|
dxSmartNotifySubscribed = false
|
||||||
|
requiredCharsConfirmed = false
|
||||||
|
characteristics.removeAll()
|
||||||
|
configService = nil
|
||||||
|
// Brief pause before reconnecting
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
|
||||||
|
guard let self = self, let peripheral = self.peripheral else { return }
|
||||||
|
self.centralManager.connect(peripheral, options: nil)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Any other disconnect during active work = fail immediately.
|
// Any other disconnect during active work = fail immediately.
|
||||||
// Prevention philosophy: if the connection dropped, something is wrong.
|
// Prevention philosophy: if the connection dropped, something is wrong.
|
||||||
// Don't try to reconnect and resume — let the user retry cleanly.
|
// Don't try to reconnect and resume — let the user retry cleanly.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue