Skip to content

fix(node): chart local-node air-quality telemetry (orphaning + zero-suppression)#5793

Merged
jamesarich merged 1 commit into
release/2.8.0from
claude/aq-chart-repro
Jun 16, 2026
Merged

fix(node): chart local-node air-quality telemetry (orphaning + zero-suppression)#5793
jamesarich merged 1 commit into
release/2.8.0from
claude/aq-chart-repro

Conversation

@jamesarich

Copy link
Copy Markdown
Collaborator

Problem

Air-quality telemetry (#5701) shows in the in-app Debug log but never in the Air Quality chart, reported on a release/2.8.0 build with non-zero PM data from a locally-connected node. Two independent bugs.

Bug A — persistence orphaning (why nothing charts)

A local-node telemetry packet received before MyNodeInfo resolves (myNodeNum still null, e.g. early in a (re)connect) was stored in the log table under its raw from_num instead of NODE_NUM_LOCAL. The per-node chart query (getTelemetryFromeffectiveLogId) keys the local node on NODE_NUM_LOCAL and filters WHERE from_num = …, so those rows are invisible to the chart — while the Debug screen (getAllLogsUnbounded, no from_num filter) still shows them. Not air-quality-specific; it orphans any local telemetry received in that window (environment survives because it's dense enough to keep charting from post-resolve rows).

Fix (MeshMessageProcessorImpl): gate early-packet processing on isNodeDbReady.value && myNodeNum != null; flush the early buffer once both hold (the combine emits the value-pair through distinctUntilChanged so it re-fires across reconnect transitions); flushEarlyReceivedPackets null-guards myNodeNum before draining the buffer so a mid-flush regression can't drop packets.

Bug B — zero suppression (clean-air 0 µg/m³)

The chart hid present-and-zero readings via ?.takeIf { it != 0 }. A PM sensor in clean air legitimately reports 0. Removed the guards from AirQuality.getValue, the card, and the CSV export; a genuinely absent field stays null (Wire decodes an unset optional uint32 to null).

Tests

  • AirQualityChartReproTest (jvmTest) — replays the reporter's real packet bytes end-to-end through MeshMessageProcessorImpl and asserts buffer → resolve → charted under NODE_NUM_LOCAL. Fails on pre-fix code.
  • AirQualityMetricsTest — locks the zero/absent semantics of getValue (present-zero plots; absent → null → not charted).
  • MeshMessageProcessorImplTest — strengthened: no DB insert before myNodeNum resolves, plus a reconnect-toggle regression test.

Verification

spotlessCheck · detekt · assembleDebug · test · allTests · kmpSmokeCompile all green (160 tests across the two touched modules; 742 in :feature:node).

Notes

  • This is the insert-side fix only — no query-side healing of already-stored rows, since the data is QA/unreleased.
  • Out of scope: buffered packets get their received_date at async-flush time — a pre-existing trait of flushEarlyReceivedPackets (the prior code was already async).

🤖 Generated with Claude Code

…uppression)

Air-quality telemetry (PR #5701) showed in the in-app Debug log but never in
the Air Quality chart. Two independent bugs:

BUG A — persistence orphaning. A local-node telemetry packet received before
MyNodeInfo resolves (myNodeNum still null) was stored in the `log` table under
its raw from_num instead of NODE_NUM_LOCAL. Per-node chart queries
(getTelemetryFrom -> effectiveLogId) key the local node on NODE_NUM_LOCAL, so
those rows were invisible to charts while the unfiltered Debug log still showed
them. Fix in MeshMessageProcessorImpl: gate early-packet processing on
`isNodeDbReady && myNodeNum != null`; flush the early buffer once both hold
(combine emits the value-pair through distinctUntilChanged so it re-fires across
reconnect transitions); flushEarlyReceivedPackets null-guards myNodeNum before
draining the buffer.

BUG B — zero suppression. The chart hid present-and-zero readings (a PM sensor
in clean air reports 0 ug/m3). Removed the `takeIf { it != 0 }` guards from
AirQuality.getValue, the AirQualityMetricsCard, and the CSV export; a genuinely
absent field stays null (Wire decodes an unset optional uint32 to null).

Tests: AirQualityChartReproTest (jvmTest, replays the reporter's real packet
bytes end-to-end through the insert path), AirQualityMetricsTest (locks the
zero/absent semantics), and a strengthened MeshMessageProcessorImplTest
(no insert before myNodeNum resolves + a reconnect-toggle regression).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the bugfix PR tag label Jun 13, 2026
@jamesarich jamesarich marked this pull request as ready for review June 16, 2026 13:33
@jamesarich jamesarich merged commit 6761b47 into release/2.8.0 Jun 16, 2026
15 checks passed
@jamesarich jamesarich deleted the claude/aq-chart-repro branch June 16, 2026 13:33
jamesarich added a commit that referenced this pull request Jun 16, 2026
…uppression) (#5793)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jamesarich added a commit that referenced this pull request Jun 16, 2026
…uppression) (#5793)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jamesarich added a commit that referenced this pull request Jun 16, 2026
…uppression) (#5793)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jamesarich jamesarich mentioned this pull request Jun 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix PR tag

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant