Skip to content

[Part 4/6] fix(glucose): match the official trend-arrow bucketing, classify transmitter model in core - #4

Open
ETolboom wants to merge 5 commits into
trioneer-dev:mainfrom
ETolboom:feat/trend-arrow-bucketing
Open

ETolboom wants to merge 5 commits into
trioneer-dev:mainfrom
ETolboom:feat/trend-arrow-bucketing

Conversation

@ETolboom

@ETolboom ETolboom commented Sep 24, 2026 •

Copy link
Copy Markdown

Correct trend-arrow bucketing, matching the official apps' shared trend table:

  • Every threshold belongs to the steeper arrow (the old ..<(-3) bucketing put exactly -3.0 mg/dL/min on single-down).
  • No arrow beyond ±8 mg/dL/min (reachable on the wire as Int8 tenths; was a triple arrow).
  • All three call sites (glucoseTrend(for:), G6GlucoseDisplay.trendType, settings trend symbol) now share one bucketing.

The bucketing lives in G6SensorCore as G6TrendArrow (LoopKit-free, raw values matching GlucoseTrend), so it is covered by swift test. Also moves the transmitter-model prefix classification (8… G6, 5…/C… ONE) into core as G6TransmitterModel with tests.

Stacked on #3; only the top commit is new.

Copilot AI lite review requested due to automatic review settings September 24, 2026 12:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@ETolboom ETolboom changed the title [Part 4/N] fix(glucose): match the official trend-arrow bucketing, classify transmitter model in core [Part 4/6] fix(glucose): match the official trend-arrow bucketing, classify transmitter model in core Sep 24, 2026
OSLog.log handed the [CVarArg] array to os_log for 6+ arguments, which
reads garbage pointers for each %@ and segfaults in
_os_log_fmt_flatten_object_impl. The seven-argument "Backfill
acknowledged" line hit this on every backfill, crash-looping the app.

The fallback now asserts in debug and logs the pre-rendered line as a
single argument in release. The backfill ack line is collapsed to one
argument.
…ensor work in the simulator

Extract the pending-command logic into a pure CommandQueue value type
(supersede-on-enqueue, 5-minute stale-calibration drop, raw-value
persistence round-trip) with unit tests, and mirror didComplete into
enqueue on the simulator, where no link will ever drain the queue.

Also: stop simulated readings once no session is active, and mark
Locked.mutate @discardableResult (both copies).
…ard, discovery timeout

PeripheralManager.didUpdateValueFor: bind the condition's characteristic
and compare with == instead of shadowing the parameter (any
characteristic's update could satisfy a pending command's condition),
and forward unclaimed notifications to the delegate even while a
command is in flight (backfill frames were dropped mid-command).

didComplete(.stopSensor): emit a .sensorEnd persisted event before
clearing the session dates; the simulator drain path mirrors it.

transmitterExpirationDate stays nil until the first version read: the
fallback lifetime is a guess and a 180-day Anubis would alert as
expired at day 90.

Service discovery timeout 2s -> 10s. Battery re-arm reads the persisted
state.lastBatteryReadDate instead of a transient ivar that was nil after
every relaunch. UInt16(clamping:) for the persisted expiry-days Int
fallback, matching G6CGMManagerState.
…smitter model in core

The old thresholds (..<(-3) style) put a boundary rate like exactly
-3.0 mg/dL/min on the single-down arrow where the official apps and
CGMBLEKit put it on the steeper one, and mapped implausible rates
(|rate| > 8, reachable over the wire as Int8 tenths) to a triple arrow
where the apps show none.

The bucketing now lives in G6SensorCore as G6TrendArrow (LoopKit-free,
raw values matching GlucoseTrend for a one-line bridge) so it is covered
by swift test, and all three call sites (glucoseTrend(for:),
G6GlucoseDisplay.trendType, settings trend symbol) share it.

Also moves the transmitter-model prefix classification (8.. G6, 5../C..
ONE) into core as G6TransmitterModel with TransmitterID.model, so the
mapping is unit-tested; deviceModel keeps returning the display string.
@ETolboom
ETolboom force-pushed the feat/trend-arrow-bucketing branch from 2d0205a to 10cfa65 Compare September 29, 2026 10:57
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.

2 participants