Skip to content

10.1: live RSSI, honest rename, firmware reinstall, real download progress, centered confirms#13

Merged
lkasso merged 13 commits into
mainfrom
connected-rssi-and-rename-broadcast
Jul 19, 2026
Merged

10.1: live RSSI, honest rename, firmware reinstall, real download progress, centered confirms#13
lkasso merged 13 commits into
mainfrom
connected-rssi-and-rename-broadcast

Conversation

@lkasso

@lkasso lkasso commented Jul 19, 2026

Copy link
Copy Markdown
Member

First 10.1 changeset (main is tagged v10.0 at the submitted build). Grew from two warm-ups into a full field-testing session — every feature and fix below was verified on real boards (MMS + MMR, iPhone + Mac) as it landed.

Live RSSI for the connected board

Boards stop advertising once connected, so advertisement RSSI freezes — and the app showed no signal at all for a connected board (beginRSSIPolling existed, uncalled). Polling now lives in AppStore (the connection-lifecycle owner): readRSSI() every 3 s → connectedRSSI, stopped by every disconnect path. Surfaced three ways, each refined by field feedback:

  • Scan row's Connected badge: green dot + text + green-tinted bars, fixedSize so it never wraps (dBm text removed — it forced two lines).
  • Device header card: blue RSSIPill (scan-screen styling) in the top row beside the state pill; MAC dropped to .callout + minimumScaleFactor so the row never wraps. (A pill-row placement with MMS/MMRL abbreviations was tried and reverted.)
  • Device Info: plain Signal value row — Battery also converted to a plain row so the whole Identity section has identical row anatomy.

Rename actually works — and visibly

  • SDK: updateMACAdvertisement(advertisedName:) re-issues the MAC broadcast without stacking macros (no per-macro erase exists → erase-all + re-record; SDK documented as the board's sole macro owner). New MetaWearScanner.noteAdvertisedName(_:for:) for the known-stale cache case.
  • App: on rename the advertised-name cache and the synced RememberedDevice record update immediately (CloudKit carries the name to other devices without a reconnect cycle); the broadcast refresh is gated on host-configured or observed-on-air (fixes cross-host: renaming a board the other device configured used to leave the old name broadcasting forever); Save is disabled for invalid names with the rules in the footer; errors finally alert (lastError was recorded but never presented); success pops back to the device page where the new name in the header is the confirmation.

Reinstall latest firmware on an up-to-date board

Settings → Firmware's "Up to date" state gains Reinstall Firmware behind an explicit confirmation (on-board logs/macros/settings are erased). SDK: updateFirmwareToLatest(forceReinstall:) skips the newer-than gate; the hardened DFU pipeline applies unchanged. Since a flash wipes macros, any successful update now re-establishes the MAC-broadcast macro — closing a lurking gap where an updated board went anonymous after its next power cycle.

Real download progress

The log-download bar jumped 0 → 100: the readout command's notify delta was 0, which disables intermediate 0x08 progress notifications entirely (spec, Logging 0x06). Demo Mode masked it — the demo transport fabricates progress regardless. Delta is now nEntries/100 (floor 1): ~100 evenly spaced updates; runDownload's per-notification snapshots were already correct and waiting.

Centered confirmations

All four destructive confirms (factory reset, clear logs, update, reinstall) converted from confirmationDialog (an anchored popover on iPad/Mac that lands in odd places) to alert, which centers on every platform.

Validation

  • 1040/1040 SPM tests, full app suite green, CI green.
  • Field-verified during development: live RSSI in all three placements, rename round-trip (immediate UI + on-air name propagation to the second device), reinstall flow, download progress bar gliding.

🤖 Generated with Claude Code

lkasso and others added 4 commits July 18, 2026 18:18
Boards stop advertising once connected, so advertisement RSSI freezes
the moment a connection succeeds — and the app showed no signal
strength at all for a connected board. ScannerViewModel had a fully
built beginRSSIPolling that nothing ever called.

Polling now lives in AppStore, which owns the connection lifecycle:
readRSSI() every 3 s into connectedRSSI, started on successful connect
and stopped by every disconnect path. The scan row's Connected badge
carries live bars + dBm, and Device Info gains a Signal row next to
Battery. The dead ScannerViewModel polling is removed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The scan response freezes its embedded name at configuration time
(documented limitation of the MAC broadcast), so a renamed board kept
advertising its old name indefinitely.

- SDK: MetaWearDevice.updateMACAdvertisement(advertisedName:) re-issues
  the broadcast WITHOUT stacking macros — the Macro module has no
  per-macro erase, so it erases all macros and re-records the one this
  SDK owns (documented: the MAC broadcast is treated as the board's
  sole macro; custom-macro users must re-record).
- App: after a successful rename of a board this app configured
  (macAdvertisementConfigured gate), the broadcast is refreshed with
  the new name. Best-effort — a failure leaves the old name on air
  until the next reconfiguration and never blocks the rename.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Recovery path for a board misbehaving on current firmware: Settings ->
Firmware's "Up to date" state gains a Reinstall Firmware button (its own
confirmation, spelling out that on-board logs/macros/settings are
erased). SDK: updateFirmwareToLatest(forceReinstall:) fetches
latestBuild directly instead of the newer-than gate; everything
downstream (bootloader interlock, staged flash, retry) applies as-is.

Because a flash wipes on-board macros, a successful update (forced or
normal) now re-establishes the MAC-broadcast macro on boards this host
configured — via the erase-and-re-record path so the outcome is one
macro regardless of what survived — or boards would turn anonymous
again after their next power cycle.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Field feedback: the badge with "Connected" + bars + dBm overflowed the
scan row onto two lines, and the bars rendered in the accent blue next
to the green text. The badge now shows dot + "Connected" + bars tinted
to match (RSSIBars gains a tint parameter, defaulting to the accent so
other call sites are unchanged), with fixedSize so it can never wrap —
the precise dBm reading lives in Device Info's Signal row.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lkasso lkasso changed the title 10.1 warm-ups: live connected RSSI + rename refreshes the MAC broadcast 10.1 warm-ups: live connected RSSI, rename refreshes broadcast, firmware reinstall Jul 19, 2026
lkasso and others added 9 commits July 18, 2026 20:30
The connected-device header's pill row (battery + model + firmware) had
no space for the new live RSSI. MWModel gains shortName ("MMS", "MMRL")
for space-constrained UI; the header uses it and adds a signal pill —
bars + dBm from AppStore's connection poll — after the firmware tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Second placement attempt after reverting the pill-row version: the
signal now sits in the header's TOP row beside the state pill, where
there's free width, as a reusable RSSIPill using the same blue capsule
styling as the scan screen's "available" badge (bars + dBm, info tint).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drops it from title3 to callout and lets it shrink to 70% on narrow
phones instead of wrapping.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The BatteryPill capsule and the custom Signal HStack made those two
rows taller than the surrounding LabeledContent value rows, breaking
the section's rhythm. Both are now plain value rows ('82%', '-48 dBm');
the richer pill treatments stay in the device header card.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
confirmationDialog renders as a popover anchored to the triggering
control on iPad/Mac and lands in odd places; alert centers on screen on
every platform. Converts all four settings-screen confirms (factory
reset, clear logs, update firmware, reinstall firmware) with identical
titles, messages, and button roles.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Field report: the log-download bar jumped 0 to 100 with nothing in
between. The readout command's second uint32 is "notify every N entries
transferred" (spec, Logging 0x06) — we passed 0, which disables
intermediate 0x08 progress notifications entirely, so real firmware
sent only the final remaining==0 notice. (Demo Mode masked it: the demo
transport fabricates periodic progress regardless of the delta.)
runDownload was already built to yield a snapshot per notification.

Delta is now nEntries/100 (floor 1): ~100 progress updates per
download regardless of size.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Field report: renaming a board appeared to do nothing. Four stacked
causes:

1. Every displayed name reads the scanner's advertised-name cache,
   which only updates from advertisements — and a CONNECTED board
   doesn't advertise, so nothing on screen could change until a full
   disconnect + rescan + reconnect cycle. The rename now injects the
   expected name into the cache (new scanner API noteAdvertisedName,
   documented for exactly this known-stale case; the next real
   advertisement reconciles).
2. The synced RememberedDevice record only picked the name up on a
   future reconnect. AppStore.renameRememberedDevice updates it
   immediately — visible in the scan list now, and CloudKit carries it
   to the user's other devices without waiting.
3. Rename/factory-reset errors were recorded in lastError but nothing
   in Settings presented them, so an invalid name (>26 chars, odd
   characters) failed in complete silence. Settings now alerts on
   lastError, disables Save while the draft is invalid, and states the
   rules in the section footer.
4. The MAC-broadcast name refresh was gated on the HOST-LOCAL
   configured set, so renaming a board configured by the user's other
   device skipped the refresh and the old name kept broadcasting
   forever. The gate now also accepts an observed MAC advertisement.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The new name in the device header is the confirmation. rename(to:) now
reports success so Settings only dismisses when the board accepted the
name; failures stay put with the error alert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lkasso lkasso changed the title 10.1 warm-ups: live connected RSSI, rename refreshes broadcast, firmware reinstall 10.1: live RSSI, honest rename, firmware reinstall, real download progress, centered confirms Jul 19, 2026
@lkasso
lkasso merged commit 8b9ce81 into main Jul 19, 2026
5 checks passed
@lkasso
lkasso deleted the connected-rssi-and-rename-broadcast branch July 19, 2026 05:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant