Skip to content

Make manual G7 pairing robust when other sensors are nearby - #70

Merged
ps2 merged 2 commits into
next-devfrom
fix/g7-manual-pairing-neighbors
Sep 22, 2026
Merged

ps2 merged 2 commits into
next-devfrom
fix/g7-manual-pairing-neighbors

Conversation

@ps2

@ps2 ps2 commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Problem

Users report that entering the 4-digit pairing code manually fails, but scanning the applicator works — with the same code.

A pairing code does not identify a sensor over the air (the advertised DXCMxx name is unrelated to it). Only a scanned serial identifies the sensor. So with more than one G7 in range the two paths diverge:

  • Scan: the serial filters discovery to the one sensor (couldHaveSerial), so the right sensor is tried immediately.
  • Manual: no serial → every G7 in range becomes a candidate and gets a full (failed) handshake.

A user's device log (multiple sensors present) showed a manual run trying two neighbour sensors — each ending in "This sensor does not match the pairing code entered" — before finally reaching the user's own sensor (its slot held, so deprioritised and discovered last) and pairing successfully ~4½ minutes in. Two things made this fail in practice:

  1. Premature give-up. On a code mismatch against the last currently discovered candidate, the planner gave up immediately (giveUpfail) — even with 19 minutes left on the 20-minute scan clock and the user's own sensor about to advertise. Meanwhile the empty-scan watchdog only fires when nothing was found, so "one wrong neighbour" failed instantly while "nothing at all" waited the full timeout.

  2. Order ignored proximity. Candidates were ordered by slot class (unheld before held) then discovery order, so a distant neighbour discovered first was tried before the sensor in the user's hand.

Fix

  • Keep scanning after a mismatch in manual entry. A mismatch there means wrong sensor, not wrong code, so the run keeps looking until the scan deadline. A scan still stops on a mismatch (keepScanningWhenExhausted is off when a serial is known), since there it is the one intended sensor and a mismatch is genuinely a wrong code.
  • Order candidates by signal strength within a class. Pairing happens with the phone held up to the freshly inserted sensor, so the intended one is usually (not always) the nearest and loudest — so the strongest signal goes first. Signal strength orders within the unheld/held classes, never across them (a held sensor is still likely to reject us). RSSI is plumbed from the discovery callback through the planner (G7Sensor ignores it; only pairing uses it).
  • Screen note that pairing may check several nearby sensors in turn, so a multi-sensor scan does not look stuck.

Tests

G7PairingPlannerTests gains coverage for signal-strength ordering (within-class, not across the held/free boundary, unknown-signal fallback, re-ordering on a fresh reading) and for keep-scanning-vs-give-up by mode. All 16 planner tests pass; full LoopWorkspace builds clean.

Notes / follow-ups

  • Within-class RSSI ordering intentionally does not promote a strong held candidate ahead of unheld ones (lockout protection). If we later want the user's recently-used (held) sensor tried sooner, a strong-signal-crosses-classes heuristic could be considered separately.
  • The "proofs did not verify under our transcript format (advisory)" log line appears on successful pairings too — benign, not touched here.

ps2 added 2 commits September 21, 2026 23:57
A 4-digit pairing code does not identify a sensor over the air, so with
several G7s in range pairing must try each until one matches the code.
Two problems made the manual path fail where a scan (which knows the
serial and filters to one sensor) succeeded:

- On a code mismatch against the last discovered sensor, the run gave up
  immediately, even with the scan clock still running and the user's own
  sensor about to advertise. A mismatch in manual entry only means wrong
  sensor, not wrong code, so keep scanning until the deadline. A scan
  still stops on a mismatch, since there it is the one intended sensor.

- Candidates were ordered only by slot class and discovery order, so a
  distant neighbour discovered first was tried before the sensor in the
  user's hand. Order by signal strength within a class as well: the
  sensor being paired is nearest, so it goes first. RSSI is plumbed from
  the discovery callback through to the planner.

Adds a pairing-screen note that pairing may check several nearby sensors
in turn, so a multi-sensor scan does not look stuck.
Comment-only. The intended sensor is usually nearest because the phone is
held up to the freshly inserted sensor during pairing, not because it is
in the user's hand.
@ps2
ps2 merged commit 0843fac into next-dev Sep 22, 2026
trioneer-dev pushed a commit to loopandlearn/G7SensorKit that referenced this pull request Sep 22, 2026
Brings LoopKit#70 (manual pairing robust when other sensors are
nearby) and LoopKit#71 (Dexcom Share upload with follower management). LoopKit#67 is now
merged upstream, so this is the first merge rather than a rebase onto it.

No new shims needed: the new code introduces no LoopQuantity/LoopUnit, no
async acknowledgeAlert and no isInoperable, and our adaptations survived
the merge untouched.
dnzxy added a commit to nightscout/Trio that referenced this pull request Sep 22, 2026
Picks up LoopKit/G7SensorKit#70 (manual pairing robust when other sensors
are nearby) and #71 (Dexcom Share upload with follower management), merged
into feat/trio-g7-direct. No Trio-side changes needed.
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