Skip to content

feat: add air quality telemetry display (PM1.0, PM2.5, PM10, CO2)#5701

Merged
jamesarich merged 5 commits into
release/2.8.0from
20260601-074653-air-quality-telemetry
Jun 4, 2026
Merged

feat: add air quality telemetry display (PM1.0, PM2.5, PM10, CO2)#5701
jamesarich merged 5 commits into
release/2.8.0from
20260601-074653-air-quality-telemetry

Conversation

@jamesarich
Copy link
Copy Markdown
Collaborator

Air Quality Telemetry Display

The AirQualityMetrics proto has existed in the firmware for some time, but the Android app never stored or displayed it. This PR adds full support for viewing air quality sensor data -- info cards on the node detail screen, a dedicated log screen with interactive charts, and CSV export.

Implements the design guidance from meshtastic/design#51 and meshtastic/design#53 (Oscar's recommendations for CO2 severity thresholds and thin-line charts).

Approach

  • Database: Added air_quality_metrics BLOB column to NodeEntity with Room auto-migration (v38 -> v39). Follows the same serialized-proto pattern as environment_metrics and power_metrics.
  • Packet handling: Extended TelemetryPacketHandlerImpl to process the air_quality_metrics oneof variant and persist it on the node entity.
  • Info cards: New AirQualityMetrics composable on the node detail screen showing PM1.0, PM2.5, PM10, and CO2 with color-coded CO2 severity (Good/Stuffy/Poor/Unsafe/Evacuate thresholds per Oscar's guidance).
  • Log screen: Full metrics history with selectable chart series, metric chips, scrollable history cards, and CSV export. Registered as NodeDetailRoute.AirQualityMetrics with navigation wired up.
  • Request support: The existing telemetry request infrastructure already handled air quality requests -- only the response path was missing.

Notable decisions

  • CO2 severity uses a Co2Severity enum in core:ui with color thresholds: <400 Good, <1000 Stuffy, <2000 Poor, <5000 Unsafe, >=5000 Evacuate.
  • Zero-value filtering (takeIf { it != 0 }) is a known trade-off with proto3 semantics -- legitimate 0 readings are hidden, but absent sensors don't show misleading zeros.
  • @Suppress("CyclomaticComplexMethod") on CSV export and @Suppress("LongMethod") on the chart composable are intentional -- these are inherently complex but linear functions.

Verification

  • spotlessApply + detekt -- clean
  • assembleDebug -- compiles
  • test + allTests -- all passing

jamesarich and others added 4 commits June 1, 2026 08:15
- Add defaultValue to air_quality_metrics BLOB column for Room auto-migration
- Replace non-null assertion with safe let in TelemetryPacketHandlerImpl
- Remove unused range property from Co2Severity enum

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Fix stringResource called in non-composable context (pre-resolve labels)
- Fix DateFormatter.formatShort → DateFormatter.formatDateTime
- Rename onPointSelected → onSelectPoint (detekt ParameterNaming)
- Reorder modifier param to end (detekt ComposableParamOrder)
- Add @Suppress for CyclomaticComplexMethod on CSV export

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added enhancement New feature or request repo Repository maintenance labels Jun 1, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 1, 2026

🖼️ Preview staleness check — advisory

This PR modifies UI composables but does not update any *Previews.kt files.

Previews power screenshot tests and in-app docs screenshots. Keeping them current ensures visual regression coverage stays accurate.

Changed UI files:

feature/node/src/commonMain/kotlin/org/meshtastic/feature/node/component/AirQualityMetrics.kt
feature/node/src/commonMain/kotlin/org/meshtastic/feature/node/component/InfoCard.kt
feature/node/src/commonMain/kotlin/org/meshtastic/feature/node/component/TelemetricActionsSection.kt
feature/settings/src/commonMain/kotlin/org/meshtastic/feature/settings/radio/component/LoRaConfigItemList.kt

What to check:

Pattern Preview file convention
feature/{name}/…/ui/ or component/ feature/{name}/…/*Previews.kt
core/ui/…/ core/ui/…/ (previews colocated)

Adding previews checklist:

  1. Create or update a *Previews.kt file in the same module with @PreviewLightDark
  2. Add @Suppress("PreviewPublic") if the preview is consumed by screenshot-tests
  3. Add corresponding @PreviewTest function in screenshot-tests/src/screenshotTest/
  4. Run ./gradlew :screenshot-tests:updateDebugScreenshotTest to generate reference images

If this PR does not require preview updates (e.g., logic-only change, non-visual refactor), add the skip-preview-check label to dismiss.

@jamesarich jamesarich added this to the 2.8.0 milestone Jun 1, 2026
@jamesarich jamesarich mentioned this pull request Jun 3, 2026
@jamesarich jamesarich changed the base branch from main to release/2.8.0 June 4, 2026 02:31
Resolved conflicts:
- NodeEntity.toModel(): release's direct-construction form + airQualityMetrics line
- Room schema renumbered v39 -> v40 (FTS5 owns v39): version=40, AutoMigration(39->40),
  regenerated 40.json, kept FTS5's 39.json
- proto pinned to 6b1ded4 (master HEAD)
- docs (copilot-instructions, .specify/feature.json): take release/2.8.0
@jamesarich jamesarich marked this pull request as ready for review June 4, 2026 02:43
@jamesarich jamesarich merged commit 5f6260e into release/2.8.0 Jun 4, 2026
15 checks passed
@jamesarich jamesarich deleted the 20260601-074653-air-quality-telemetry branch June 4, 2026 02:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request repo Repository maintenance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant