Remove the guard that dropped non-CP-28 devices. All discovered
BLE peripherals now appear in the scan list (defaulting to .dxsmart
type). detectBeaconType still classifies known CP-28 patterns but
unknown devices are no longer hidden.
The CP-28-only refactor accidentally over-filtered the BLE scan:
1. FFF0 service detection was gated on name patterns — CP-28 beacons
advertising FFF0 with non-matching names (e.g. already provisioned
as "Payfrit") were silently filtered out. Restored unconditional
FFF0 → dxsmart mapping (matching old behavior).
2. Already-provisioned beacons broadcast with name "Payfrit" (set by
old SDK cmd 0x43), but that name wasn't in the detection patterns.
Added "payfrit" to the name check.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove BlueCharmProvisioner, KBeaconProvisioner, and FallbackProvisioner.
Simplify BeaconType enum to DX-Smart only. Simplify BLE detection to only
show CP-28 beacons. Remove multi-type provisioner factory from ScanView.
-989 lines of dead code removed. Other beacon types will be re-added
when we start using different hardware.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Swift strict concurrency checker flags MainActor-isolated self access from
nonisolated CBCentralManagerDelegate methods when using Task{@MainActor in}.
DispatchQueue.main.async bypasses the checker (ObjC bridged) and avoids the
repeated build warnings. Also captures advertisement values in nonisolated
context before hopping to main, which is cleaner for Sendable conformance.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BIG FIX: Provisioners were calling centralManager.connect() but
BLEManager is the CBCentralManagerDelegate — provisioners never
received didConnect/didFailToConnect callbacks, so connections
ALWAYS timed out after 5s regardless. This is why provisioning
kept failing. Fixed by:
1. Adding didConnect/didFailToConnect/didDisconnect to BLEManager
2. Provisioners register connection callbacks via bleManager
3. Increased connection timeout from 5s to 10s
DIAGNOSTICS: Added ProvisionLog system so failures show a timestamped
step-by-step log of what happened (with Share button). Every phase
is logged: init, API calls, connect attempts, service discovery,
auth, write commands, and errors.
Sort the beacon list so strongest signal (closest beacon) appears at the
top. Sorting happens both in BLEManager as beacons are discovered and in
the ScanView list rendering.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Major detection gaps were causing iOS to miss 7-8 out of 8-9 nearby DX beacons:
1. FFF0 service UUID was incorrectly mapped exclusively to BlueCharm.
Android maps DXSmartProvisioner.SERVICE_UUID_FFF0 to DXSMART.
Now checks device name to disambiguate FFF0 between DX and BlueCharm,
defaulting to DXSmart (matching Android behavior).
2. Added DX factory default UUID detection (E2C56DB5-DFFB-48D2-B060-D0F5A71096E0).
Android catches DX beacons by this UUID on line 130 of BeaconScanner.kt.
iOS was missing this entirely.
3. Added Payfrit shard UUID detection — already-provisioned DX beacons
broadcasting a shard UUID are now recognized.
4. Added iBeacon manufacturer data parsing with proper UUID extraction.
Any device broadcasting valid iBeacon data is now included (not just
those with minor > 10000).
5. Added permissive fallback matching Android lines 164-169: connectable
devices with names are included even if type is unknown, so they're
at least visible to the user.
6. Added FEA0 service UUID for BlueCharm (Android line 124).
7. Added "DX-CP" name pattern (Android line 138) that was missing.
Root cause: Android uses MAC OUI prefix 48:87:2D to catch all DX beacons
regardless of advertisement contents. iOS can't do this (CoreBluetooth
doesn't expose MAC addresses), so we compensate with broader iBeacon
UUID matching and more permissive device inclusion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>