Commit graph

73 commits

Author SHA1 Message Date
f60c70f32a fix: QR scanner crash — missing NSCameraUsageDescription in Info.plist
The app crashed immediately when tapping QR scan because the Info.plist
was missing the required NSCameraUsageDescription key. iOS kills the app
with EXC_BAD_INSTRUCTION when camera access is requested without it.

Also fixes:
- Flash toggle could SIGABRT if lockForConfiguration failed (try? + unconditional unlock)
- Camera setup now logs errors instead of silently failing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 21:45:10 +00:00
1624e0e59d Merge pull request 'fix: decode actual API response format' (#29) from schwifty/fix-api-response-decoding into main 2026-03-22 21:27:15 +00:00
a1c215eb42 fix: decode actual API response format (OK + flat keys, not Success/Data)
The API returns {OK: true, BUSINESSES: [...]} but the iOS client was
decoding {Success: true, Data: [...]} which never matched — causing
"Failed to load businesses" on every call. Also fixes Business model
(BusinessID/Name vs ID/BusinessName) and ServicePoint model
(ServicePointID vs ID). All response decoders now match the real API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 21:26:42 +00:00
2242260f5a fix: align OTP auth with actual API response format
Three bugs found and fixed:
1. sendOTP was sending "ContactNumber" but API expects "Phone"
2. APIResponse expected {"Success":true,"Data":{}} but API returns {"OK":true,"UUID":"..."}
3. verifyOTP was sending "Code" but API expects "OTP"

Now decodes the raw API format directly instead of going through the
generic APIResponse wrapper (which doesn't match auth endpoints).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 20:46:55 +00:00
fd4b1bf8ca Merge schwifty/v3-clean-refactor: v3 BeaconProvisioner clean refactor with BLE timeout fixes 2026-03-22 20:15:41 +00:00
1b3b16478c fix: remove duplicate color definitions from Assets.xcassets to resolve ambiguity
PayfritGreen and PayfritGreenDark were defined in both Assets.xcassets
(as .colorset files) and in BrandColors.swift (as Color extensions).
All code references the Swift extension (.payfritGreen), so the asset
catalog versions are redundant and cause ambiguity. Removed the colorsets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:47:03 +00:00
09db3e8ec7 fix: resolve ambiguous color references by removing ShapeStyle extension
The ShapeStyle where Self == Color extension duplicated Color statics,
causing 'ambiguous use' errors in foregroundStyle/stroke/tint/background
contexts. Removed the extension entirely and use explicit Color.xxx prefix
at all call sites instead.
2026-03-22 19:40:51 +00:00
3fbb44d22c fix: add ShapeStyle extension for brand colors to resolve ambiguous dot-syntax 2026-03-22 19:34:29 +00:00
8ecd533429 fix: replace generic icon with beacon-specific icon and match Android color scheme
- App icon now uses white bg + PAYFRIT text + bluetooth beacon icon (matches Android)
- AccentColor set to Payfrit Green (#22B24B)
- Added BrandColors.swift with full Android color palette parity
- All views updated: payfritGreen replaces .blue, proper status colors throughout
- Signal strength, beacon type badges, QR scanner corners all use brand colors
- DevBanner uses warningOrange matching Android's #FF9800

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:29:35 +00:00
2496cab7f3 fix: wrap iOS 17+ APIs in @available checks for iOS 16 compat
ContentUnavailableView and .symbolEffect(.pulse) require iOS 17+
but deployment target is iOS 16. Wrapped all usages in
if #available(iOS 17.0, *) with VStack-based fallbacks for iOS 16.

Files fixed:
- ScanView.swift (4 ContentUnavailableView + 1 symbolEffect)
- QRScannerView.swift (1 ContentUnavailableView)
- BusinessListView.swift (2 ContentUnavailableView)
2026-03-22 19:20:46 +00:00
fe2ee59930 fix: resolve ambiguous toolbar(content:) in BusinessListView
Use explicit toolbar(content:) call instead of trailing closure to
disambiguate the SwiftUI toolbar modifier overload.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:15:35 +00:00
9986937f66 fix: add missing Info.plist for PayfritBeacon target
Project references PayfritBeacon/Info.plist but the file was never committed.
Includes Bluetooth and Location usage descriptions required for beacon functionality.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:10:53 +00:00
6f4dba1804 fix: add actual 1024x1024 AppIcon.png to asset catalog
Copied from payfrit-user-ios — same Payfrit brand icon.
Contents.json now references the file.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:04:42 +00:00
21a40a0a28 fix: add missing Assets.xcassets with AppIcon.appiconset
Xcode build was failing because the asset catalog referenced in
project.pbxproj didn't exist on disk. Added:
- Assets.xcassets/Contents.json
- AppIcon.appiconset/Contents.json (single 1024x1024 slot, no image yet)
- AccentColor.colorset/Contents.json

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 19:02:48 +00:00
9ffd890a62 Merge pull request 'fix: rewrite xcodeproj to match subdirectory structure' (#27) from schwifty/fix-xcodeproj-structure into main 2026-03-22 18:59:06 +00:00
023ee9b3e3 fix: rewrite xcodeproj to match new subdirectory structure
The project file referenced old flat-structure filenames (Api.swift,
BeaconScanner.swift, BLEBeaconScanner.swift, etc.) but files are now
organized into App/, Models/, Provisioners/, Services/, Utils/, Views/.

Changes:
- Added PBXGroup entries for all 6 subdirectories
- Updated all 26 Swift file references to use subdirectory paths
- Removed 6 stale references (Api.swift, BeaconScanner.swift,
  BLEBeaconScanner.swift, BeaconProvisioner.swift,
  ServicePointListView.swift, DebugLog.swift)
- Added 14 new file references (AppPrefs, AppState, BeaconConfig,
  BeaconType, Business, ServicePoint, all Provisioners, APIClient,
  APIConfig, BLEManager, SecureStorage)
- All build configurations preserved unchanged

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:58:49 +00:00
b943a291d9 fix: add missing build files referenced in xcodeproj
- payfrit-favicon-light-outlines.svg (copied from payfrit-works-ios)
- en.lproj/InfoPlist.strings (standard localization)

These were referenced in project.pbxproj but not committed to the repo,
causing build failures.
2026-03-22 18:44:08 +00:00
928c5ff28f Merge pull request 'fix: remove CocoaPods references breaking build' (#26) from koda/remove-cocoapods-refs into main 2026-03-22 18:37:43 +00:00
8bd3fb474a fix: remove all CocoaPods references from xcodeproj
The rebuild removed Podfile/Podfile.lock/Pods but left CocoaPods build
phases and xcconfig references in the project file, causing build failure.

Removed: [CP] Check Pods Manifest.lock, [CP] Embed Pods Frameworks,
Pods_PayfritBeacon.framework, all Pods xcconfig baseConfigurationReferences,
and the Pods/Frameworks groups.

The old pods (Kingfisher, SVGKit) are not imported anywhere in the
rebuilt codebase — no replacement needed.
2026-03-22 18:37:28 +00:00
075706f162 docs: add CLAUDE.md updated for new modular architecture
Reflects Schwifty's rebuild — modular provisioners, actor-based API,
secure storage, QR scanner, and updated project structure.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 18:31:56 +00:00
0c4542e62f Merge schwifty/koda-review-fixes: complete iOS beacon rebuild with code review fixes 2026-03-22 18:29:48 +00:00
38b4c987c9 fix: address all issues from koda's code review
🔴 Critical:
- DXSmartProvisioner: complete rewrite to match Android's new SDK protocol
  - Writes to FFE2 (not FFE1) using 4E4F protocol packets
  - Correct command IDs: 0x74 UUID, 0x75 Major, 0x76 Minor, 0x77 RSSI,
    0x78 AdvInt, 0x79 TxPower, 0x60 Save
  - Frame selection (0x11/0x12) + frame type (0x62 iBeacon)
  - Old SDK fallback (0x36-0x43 via FFE1 with 555555 re-auth per command)
  - Auth timing: 100ms delays (was 500ms, matches Android SDK)
- BeaconShardPool: replaced 71 pattern UUIDs with exact 64 from Android

🟡 Warnings:
- BlueCharmProvisioner: 3 fallback write methods matching Android
  (FEA3 direct → FEA1 raw → FEA1 indexed), legacy FFF0 support,
  added "minew123" and "bc04p" passwords (5 total, was 3)
- BeaconBanList: added 4 missing prefixes (8492E75F, A0B13730,
  EBEFD083, B5B182C7), full UUID ban list, getBanReason() helper
- BLEManager: documented MAC OUI limitation (48:87:2D not available
  on iOS via CoreBluetooth)

🔵 Info:
- APIClient: added get_beacon_config endpoint for server-configured values
- ScanView: unknown beacon type now tries KBeacon→DXSmart→BlueCharm
  fallback chain via new FallbackProvisioner
- DXSmartProvisioner: added readFrame2() for post-write verification

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 17:25:55 +00:00
6832a8ad53 feat: add QR scanner view + 7 missing API endpoints
- QRScannerView: AVFoundation camera + barcode/QR detection with
  flashlight toggle, viewfinder overlay, MAC/UUID pattern recognition
- New API endpoints: deleteServicePoint, updateServicePoint,
  listBeacons, decommissionBeacon, lookupByMac, getBeaconStatus, getProfile
- Wire QR scanner into ScanView with BLE Scan + QR Scan side-by-side
- MAC address lookup on scan to check if beacon already registered
- Updated Xcode project file with new source
2026-03-22 17:17:49 +00:00
cfa78679be feat: complete rebuild of PayfritBeacon iOS from scratch
100% fresh codebase — no legacy code carried over. Built against
the Android beacon app as the behavioral spec.

Architecture:
- App: SwiftUI @main, AppState-driven navigation, Keychain storage
- Views: LoginView (OTP + biometric), BusinessListView, ScanView (provisioning hub)
- Models: Business, ServicePoint, BeaconConfig, BeaconType, DiscoveredBeacon
- Services: APIClient (actor, async/await), BLEManager (CoreBluetooth scanner)
- Provisioners: KBeacon, DXSmart (2-step auth + flashing), BlueCharm
- Utils: UUIDFormatting, BeaconBanList, BeaconShardPool (64 shards)

Matches Android feature parity:
- 4-screen flow: Login → Business Select → Scan/Provision
- 3 beacon types with correct GATT protocols and timeouts
- Namespace allocation via beacon-sharding API
- Smart service point naming (Table N auto-increment)
- DXSmart special flow (connect → flash → user confirms → write)
- Biometric auth, dev/prod build configs, DEV banner overlay

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 17:13:36 +00:00
66053508d3 refactor: v3 BeaconProvisioner — clean restart from pre-refactor baseline
Replaces the v2 refactor with a clean v3 rewrite built from the working
pre-refactor code (d123d25). Preserves all battle-tested BLE fixes while
removing dead code and simplifying state management. See schwifty/v3-clean-refactor
branch for full details.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 05:08:21 +00:00
58facfda47 refactor: v3 BeaconProvisioner — clean refactor from pre-refactor baseline
Starting fresh from the working pre-refactor code (d123d25), this is a clean
rewrite that preserves all the hard-won BLE reliability fixes while simplifying
the architecture. Key changes:

What's preserved (battle-tested, working):
- Exact same 16-step write sequence (DeviceName, Frame1, Frame2 iBeacon, Save)
- Same DX-Smart packet format (4E 4F CMD LEN DATA XOR)
- Response gating between writes (1s timeout, matches Android)
- Adaptive delays (1s for frame select/type, 0.8s for UUID, 0.5s base)
- FFE2 missing → full disconnect/reconnect (CoreBluetooth stale GATT cache)
- SaveConfig write-error = success (beacon reboots immediately)
- Disconnect recovery with write position resume
- Multi-password auth (555555, dx1234, 000000)
- Skip device info read (0x30 causes disconnects, MAC is optional)
- Skip extra frame disables (frames 3-6 untouched, fewer writes = fewer disconnects)

What's cleaned up:
- Removed dead device info provisioning code (was already skipped)
- Removed processDeviceInfoForProvisioning (dead code)
- Removed awaitingDeviceInfoForProvisioning flag
- Removed skipDeviceInfoRead flag
- Removed deviceInfoRetryCount (no longer needed)
- Consolidated charRediscovery into handleFFE2Missing()
- Renamed state vars for clarity (dxSmartWriteIndex → writeIndex, etc.)
- Extracted scheduleGlobalTimeout (was inline closure)
- Added cancelAllTimers() helper
- Reduced mutable state from ~30 vars to ~22

1652 lines → 1441 lines (-211 lines, -13%)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 05:07:58 +00:00
37e3364e1e fix: resolve FFE2 characteristic lost during write race condition
When CoreBluetooth renegotiates connection parameters (common at edge-of-range),
it can invalidate cached CBCharacteristic references, causing the characteristics
dictionary to return nil mid-write. This resulted in "FFE2 characteristic lost
during write" failures.

Changes:
- Add resolveCharacteristic() with live service fallback when cache misses
- Implement peripheral(_:didModifyServices:) to handle service invalidation
- Replace all direct characteristics[] lookups with resolveCharacteristic()
- Eliminates force-unwrap on FFE1 notification subscribe

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 04:48:04 +00:00
fc13986396 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
2026-03-22 04:37:52 +00:00
972291e93b 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>
2026-03-22 04:28:52 +00:00
1e3e0198b1 refactor: v2 BeaconProvisioner — prevention over recovery
Major cleanup of the BLE provisioning flow:

- Remove frames 3-6 disable steps (no longer overwriting "extra frames")
  Only Frame 1 (device info) and Frame 2 (iBeacon) are configured now.
  Command count drops from 24 to 16.

- Eliminate 5 layers of retry/reconnect/resume logic:
  No more disconnect retry counter (was 5 retries)
  No more resume-from-position after reconnect
  No more characteristic re-discovery attempts
  No more device info read/skip dance
  If connection drops mid-write, fail cleanly — let user retry.

- Prevention approach: verify all 3 required characteristics (FFE1/FFE2/FFE3)
  are confirmed before starting any writes. No mid-write discovery.

- Add POST_AUTH_DELAY (1.5s) to let beacon stabilize after auth before writes.

- Keep response gating (wait for FFE1 after each write) — this is the key
  mechanism that prevents blasting commands faster than the MCU can handle.

- 191 insertions, 476 deletions — nearly half the code removed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 03:57:02 +00:00
d123d2561a fix: slim provisioning — skip extra frame disables + full reconnect on FFE2 miss
Two key changes:

1. Remove frames 3-6 disable commands (was steps 16-23, 8 extra BLE writes).
   We only configure Frame 1 (device info) and Frame 2 (iBeacon), then save.
   Fewer writes = fewer chances for supervision timeout disconnects.

2. When FFE2 characteristic goes missing after a disconnect, do a full
   disconnect → reconnect → re-discover services → re-auth → resume cycle
   instead of trying to rediscover characteristics on the same (stale GATT)
   connection. CoreBluetooth returns cached results on the same connection,
   so FFE2 stays missing. Full reconnect forces a fresh GATT discovery.

Write sequence is now 16 steps (down from 24).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 03:54:29 +00:00
f0d2b2ae90 fix: add timeout for characteristic rediscovery to prevent hang
When FFE2 goes missing during writes, the rediscovery path had no
timeout — if CoreBluetooth never called back didDiscoverCharacteristics,
the app would hang at "Re-discovering characteristics..." indefinitely.

Adds a 5-second timeout per rediscovery attempt. If it fires, it either
retries (up to MAX_CHAR_REDISCOVERY) or fails with .timeout instead of
hanging forever.
2026-03-22 03:18:43 +00:00
813198599a Merge pull request 'fix: response gating between BLE writes (matches Android)' (#15) from schwifty/response-gating-fix into main 2026-03-22 03:12:49 +00:00
057a215a50 Merge pull request 'fix: retry char discovery when FFE2 missing after disconnect' (#14) from schwifty/fix-ffe2-missing-after-disconnect into main 2026-03-22 03:12:29 +00:00
41c26acad3 fix: add response gating between BLE writes to prevent beacon disconnects
Root cause: iOS was firing the next GATT command as soon as the BLE write
ACK arrived, without waiting for the beacon's FFE1 notification response.
Android explicitly waits up to 1s for the beacon to respond (via
responseChannel.receive) before sending the next command. This gives the
beacon MCU time to process each command before the next one arrives.

Without this gate, the beacon gets overwhelmed and drops the BLE connection
(supervision timeout), causing the "DX Smart command characteristic" error
John reported after repeated disconnects.

Changes:
- Add awaitingCommandResponse flag + 1s response gate timer
- After each FFE2 write success, wait for FFE1 notification before advancing
- If no response within 1s, advance anyway (some commands don't respond)
- Check for 4E 4F 00 rejection pattern (matches Android)
- Clean up gate timer on disconnect, cleanup, and state resets

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 03:08:53 +00:00
9319cad2d6 fix: retry characteristic discovery when FFE2 missing after disconnect
After 2+ disconnects during provisioning, the beacon's BLE stack can
return incomplete characteristic discovery results. Instead of hard-
failing with "DX-Smart command characteristic (FFE2) not found", we
now re-trigger characteristic discovery (up to 2 attempts) and resume
writing from the saved position once FFE2 is found.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 03:03:08 +00:00
d44ca47f36 Merge pull request 'fix: prevent beacon disconnects during provisioning' (#13) from schwifty/fix-beacon-disconnect-root-cause into main 2026-03-22 02:57:35 +00:00
bfbc2a5d8c fix: adaptive inter-command delays to prevent BLE supervision timeouts
Root cause: DX-Smart CP28 beacons were disconnecting during provisioning
because the 0.3s inter-command delay was too fast for the beacon's MCU.
Frame selection (0x11-0x16) and type commands (0x61, 0x62) trigger internal
state changes that need processing time. Rapid writes caused the beacon to
miss BLE connection events, triggering link-layer supervision timeouts.

Changes:
- Base delay: 0.3s → 0.5s for all commands
- Heavy delay: 1.0s after frame select/type commands (MCU state change)
- Large payload delay: 0.8s after UUID writes (21 bytes)
- Resume delay: 0.5s → 1.5s after reconnect (let BLE stack stabilize)
- Non-fatal skip delay: 0.15s → 0.5s

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 02:53:37 +00:00
aeab67ea64 fix: resume writing from saved position on BLE disconnect instead of restarting
Previously, when the beacon disconnected mid-write, the reconnect handler
cleared the entire command queue and reset writeIndex to 0, causing all 24
commands to be re-sent from scratch on every reconnect. This could confuse
the beacon firmware with duplicate config writes and wasted reconnect cycles.

Changes:
- On disconnect during writing, PRESERVE command queue and write index
- After reconnect + re-auth, resume from the last command instead of rebuilding
- Increase MAX_DISCONNECT_RETRIES from 3 to 5 (resume is lightweight)
- Increase inter-command delay from 150ms to 300ms for firmware breathing room
- Increase global timeout from 45s to 90s to accommodate more retries
- Add resumeWriteAfterDisconnect flag to control post-auth flow

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 02:48:42 +00:00
292821622e Merge pull request 'fix: live progress display + better disconnect resilience' (#11) from schwifty/fix-progress-and-reconnect into main 2026-03-22 02:41:32 +00:00
cb3e8107fc fix: show live provisioning progress + improve disconnect resilience
- Wire provisioner.progress into assignment sheet UI (was showing static
  "Provisioning beacon..." instead of live updates like "Connecting...",
  "Authenticating...", "Writing config 1/24...")
- Increase disconnect retries from 2 to 3 with longer backoff (3s/4s/5s)
- Cancel write timeout timer on disconnect to prevent double-failure
- Bump global timeout from 30s to 45s for extra retry headroom
- Improve error message with actionable guidance ("move closer and retry")
2026-03-22 02:38:36 +00:00
cabb2825d8 Merge pull request 'fix: per-write timeouts + reduced inter-write delay' (#10) from schwifty/per-write-timeout-and-mtu into main 2026-03-22 02:17:18 +00:00
91669515bd fix: add per-write timeouts and reduce inter-write delay to match Android
The iOS provisioner had no per-write timeout — if a BLE write callback
never came back, the operation hung until the 30s global timeout, by
which point the connection was likely dead. Android uses a 5-second
per-write timeout with withTimeoutOrNull(5000L).

Changes:
- Add 5-second per-write timeout with retry (1 retry per command)
- On timeout: retry once, skip if non-fatal (steps 1-6), or fail
- SaveConfig timeout treated as success (beacon reboots = no callback)
- Reduce inter-write delay from 200ms to 150ms (Android uses 100ms)
- Log negotiated MTU on connect to diagnose packet size issues
- Cancel write timeout on cleanup/succeed/fail to prevent stale timers

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 02:14:32 +00:00
28aefd1bdf fix: broaden disconnect retry to cover all active provisioning phases
Previously retry logic only caught disconnects during .authenticating
and .writing states. Beacons can also drop during .discoveringServices
(characteristic discovery) and .verifying (broadcast check), which
would bypass retry and immediately hard-fail.

Now all active provisioning phases get the same reconnect retry
treatment with backoff delays.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 00:23:01 +00:00
34e8ea0bab Merge pull request 'fix: reconnect retry for unexpected BLE disconnects' (#8) from schwifty/reconnect-on-unexpected-disconnect into main 2026-03-22 00:17:30 +00:00
df6601c50b fix: add reconnect retry for unexpected disconnects during auth/write
Instead of immediately failing on disconnect during authenticating or
writing states, retry up to 2 times with backoff. Resets passwordIndex
on reconnect so re-auth starts fresh (fixes issue where burned password
attempts caused retry failures). Also fixes passwordIndex reset in the
device-info safety-net reconnect path.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 23:54:13 +00:00
e9b668cb20 Merge pull request 'fix: skip device info read to prevent disconnect failures' (#7) from schwifty/skip-device-info-read into main 2026-03-21 23:50:42 +00:00
4c1c1adf85 fix: skip device info read during provisioning to prevent disconnect failures
The DX-Smart 0x30 device info query consistently causes beacon BLE disconnects,
which exhausted the retry counter and failed provisioning. The MAC address is
optional — API falls back to iBeacon UUID as hardware ID. Device info read is
still available in readConfig/check mode where it doesn't block provisioning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 23:50:08 +00:00
720c560760 Merge remote-tracking branch 'origin/schwifty/fix-device-info-retry-counter' 2026-03-21 23:37:28 +00:00
07c5a22315 Merge remote-tracking branch 'origin/schwifty/fix-device-info-disconnect-retry' 2026-03-21 23:37:26 +00:00