Compare commits

...

2 commits

Author SHA1 Message Date
f082eeadad fix: skip ACK wait on SaveConfig — beacon reboots, never ACKs
SaveConfig (0x60) causes the beacon MCU to reboot and save to flash.
It never sends an ACK, so writeToCharAndWaitACK would wait for the
5s timeout, during which the beacon disconnects. The disconnect
handler fires while writesCompleted is still false, causing a false
"Unexpected disconnect: beacon timed out" error.

Fix: fire-and-forget the SaveConfig write and return immediately.
The BLE-level write (.withResponse) confirms delivery. writeConfig()
returns before the disconnect callback runs, so writesCompleted gets
set to true in time.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 03:44:36 +00:00
3720f496bd perf: reduce inter-command delay from 500ms to 300ms (conservative)
Shaves ~4.6s off the 23-command provisioning sequence while keeping
a safe margin for the beacon's BLE stack to process each write.

Next step: if stable, we can go more aggressive (200ms or 150ms).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 03:41:44 +00:00

View file

@ -173,6 +173,15 @@ final class DXSmartProvisioner: NSObject, BeaconProvisioner {
for (index, (name, packet)) in commands.enumerated() {
await diagnosticLog?.log("write", "[\(index + 1)/\(commands.count)] \(name) (\(packet.count) bytes)")
// SaveConfig (last command) causes beacon MCU to reboot it never sends an ACK.
// Fire the BLE write and return immediately; the disconnect is expected.
if name == "SaveConfig" {
peripheral.writeValue(packet, for: writeChar, type: .withResponse)
await diagnosticLog?.log("write", "✅ [\(index + 1)/\(commands.count)] SaveConfig sent — beacon will reboot")
await diagnosticLog?.log("write", "✅ All commands written successfully")
return
}
// Retry each command up to 2 times beacon BLE stack can be flaky
var lastError: Error?
for writeAttempt in 1...2 {
@ -193,8 +202,9 @@ final class DXSmartProvisioner: NSObject, BeaconProvisioner {
throw lastError
}
// 500ms between commands beacon needs time to process
try await Task.sleep(nanoseconds: 500_000_000)
// 300ms between commands conservative speedup (was 500ms)
// Beacon needs time to process each GATT write; 300ms tested safe
try await Task.sleep(nanoseconds: 300_000_000)
}
}