fix: add pre-auth stabilization delay to prevent disconnect during authentication

DX-Smart beacons drop the BLE connection when a password write (FFE3) arrives
too quickly after service/characteristic discovery. The v2 refactor had a
POST_AUTH_DELAY (1.5s) before writes, but nothing before the auth attempt itself.

Adds PRE_AUTH_DELAY (0.8s) after characteristic discovery + FFE1 subscription
before the first password write. This gives the beacon MCU time to stabilize
after the discovery handshake.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Schwifty 2026-03-22 04:28:52 +00:00
parent 1e3e0198b1
commit 972291e93b

View file

@ -198,6 +198,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
// Prevention > recovery: generous delays prevent supervision timeouts.
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 PRE_AUTH_DELAY: Double = 0.8 // After discovery, before first auth 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
@ -409,9 +410,13 @@ class BeaconProvisioner: NSObject, ObservableObject {
DebugLog.shared.log("BLE: Subscribing to FFE1 notifications")
peripheral?.setNotifyValue(true, for: characteristics[BeaconProvisioner.DXSMART_NOTIFY_CHAR]!)
} else {
DebugLog.shared.log("BLE: FFE1 not found, proceeding to auth directly")
DebugLog.shared.log("BLE: FFE1 not found, proceeding to auth after stabilization delay")
dxSmartNotifySubscribed = true
dxSmartAuthenticate()
// Same pre-auth delay even without FFE1 beacon still needs time after discovery
DebugLog.shared.log("BLE: Waiting \(BeaconProvisioner.PRE_AUTH_DELAY)s before auth...")
DispatchQueue.main.asyncAfter(deadline: .now() + BeaconProvisioner.PRE_AUTH_DELAY) { [weak self] in
self?.dxSmartAuthenticate()
}
}
}
@ -1264,7 +1269,13 @@ extension BeaconProvisioner: CBPeripheralDelegate {
if operationMode == .readingConfig {
dxSmartReadAuth()
} else {
dxSmartAuthenticate()
// Give the beacon a moment to stabilize after discovery + notification subscribe
// before we hit it with a password write. Without this, DX-Smart beacons drop
// the connection during auth (supervision timeout).
DebugLog.shared.log("BLE: Waiting \(BeaconProvisioner.PRE_AUTH_DELAY)s before auth...")
DispatchQueue.main.asyncAfter(deadline: .now() + BeaconProvisioner.PRE_AUTH_DELAY) { [weak self] in
self?.dxSmartAuthenticate()
}
}
}
}