fix: live progress display + better disconnect resilience #11

Merged
schwifty merged 1 commit from schwifty/fix-progress-and-reconnect into main 2026-03-22 02:41:33 +00:00
2 changed files with 10 additions and 7 deletions
Showing only changes of commit cb3e8107fc - Show all commits

View file

@ -182,7 +182,7 @@ class BeaconProvisioner: NSObject, ObservableObject {
private var disconnectRetryCount = 0
private static let MAX_CONNECTION_RETRIES = 3
private static let MAX_DEVICE_INFO_RETRIES = 2
private static let MAX_DISCONNECT_RETRIES = 2
private static let MAX_DISCONNECT_RETRIES = 3
private var currentBeacon: DiscoveredBeacon?
// Per-write timeout (matches Android's 5-second per-write timeout)
@ -241,8 +241,8 @@ class BeaconProvisioner: NSObject, ObservableObject {
centralManager.connect(resolvedPeripheral, options: nil)
// Timeout after 30 seconds
DispatchQueue.main.asyncAfter(deadline: .now() + 30) { [weak self] in
// Timeout after 45 seconds (increased from 30s to accommodate 3 disconnect retries with backoff)
DispatchQueue.main.asyncAfter(deadline: .now() + 45) { [weak self] in
if self?.state != .success && self?.state != .idle {
self?.fail("Connection timeout", code: .connectionTimeout)
}
@ -1114,6 +1114,9 @@ extension BeaconProvisioner: CBCentralManagerDelegate {
return
}
// Cancel any pending write timeout disconnect supersedes it
cancelWriteTimeout()
// Unexpected disconnect during any active provisioning phase retry with full reconnect
let isActivePhase = (state == .discoveringServices || state == .authenticating || state == .writing || state == .verifying)
if isActivePhase && disconnectRetryCount < BeaconProvisioner.MAX_DISCONNECT_RETRIES {
@ -1131,7 +1134,7 @@ extension BeaconProvisioner: CBCentralManagerDelegate {
responseBuffer.removeAll()
state = .connecting
let delay = Double(disconnectRetryCount) + 1.0 // 2s, 3s backoff
let delay = Double(disconnectRetryCount) + 2.0 // 3s, 4s, 5s backoff give BLE time to settle
DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [weak self] in
guard let self = self, let beacon = self.currentBeacon else { return }
guard self.state == .connecting else { return }
@ -1145,7 +1148,7 @@ extension BeaconProvisioner: CBCentralManagerDelegate {
// All retries exhausted or disconnect in unexpected state fail
DebugLog.shared.log("BLE: UNEXPECTED disconnect — state=\(state) writeIdx=\(dxSmartWriteIndex) queueCount=\(dxSmartCommandQueue.count) authenticated=\(dxSmartAuthenticated) disconnectRetries=\(disconnectRetryCount)")
fail("Unexpected disconnect (state: \(state))", code: .disconnected)
fail("Beacon disconnected \(disconnectRetryCount + 1) times during \(state). Move closer to the beacon and try again.", code: .disconnected)
}
}

View file

@ -385,11 +385,11 @@ struct ScanView: View {
.font(.title3)
}
// Provisioning progress
// Provisioning progress show live updates from provisioner
if isProvisioning {
HStack {
ProgressView()
Text(provisioningProgress)
Text(provisioner.progress.isEmpty ? provisioningProgress : provisioner.progress)
.font(.callout)
}
.padding()