Skip to content

Flight Tracker: optional airport weather (METAR/TAF/PIREP/SIGMET)#176

Merged
ChuckBuilds merged 6 commits into
mainfrom
claude/flight-tracker-metar-taf-z1tjop
Jul 10, 2026
Merged

Flight Tracker: optional airport weather (METAR/TAF/PIREP/SIGMET)#176
ChuckBuilds merged 6 commits into
mainfrom
claude/flight-tracker-metar-taf-z1tjop

Conversation

@ChuckBuilds

@ChuckBuilds ChuckBuilds commented Jul 9, 2026

Copy link
Copy Markdown
Owner

Summary

Adds an optional, pilot-focused Airport Weather add-on to the Flight Tracker plugin: a new opt-in metar rotation view that shows METAR (color-coded decoded card + raw page), TAF, PIREP, and SIGMET/AIRMET for airports you choose, using the free NOAA Aviation Weather Center API (aviationweather.gov) — no API key or account required. Requested by a pilot who wanted the current METAR for an airport of their choice, baked into the existing plugin rather than a standalone one.

Type of change

  • New feature for an existing plugin

Plugin(s) affected

ledmatrix-flights

Related issues

N/A

Test plan

The core repo (harness, BasePlugin, TTF fonts) and the aviationweather.gov host are both unavailable in the CI/dev sandbox, so testing was done with targeted automated checks rather than the boxes below:

  • Fetcher unit tests (test/test_metar_fetcher.py, 8/8): METAR normalization (flight category, ceiling from cloud layers, altimeter hPa→inHg with an inHg pass-through guard, present weather), METAR+TAF batching/merge, cache-first + serve-stale on network error, PIREP and SIGMET parsing.
  • Renderer regression (test/test_overhead_card.py, 13/13) — unchanged, confirms existing rendering still works after the additions.
  • Manager logic exercised directly: _resolve_metar_airports (IATA→ICAO, dedup, 4-letter passthrough, junk dropped), _view_has_content('metar'), and _build_metar_pages page ordering/toggles.
  • Render preview of all five page types at 64×32 / 128×32 / 128×64 / 256×32 (non-blank + edge checks, PNGs eyeballed) using a real small monospace font to approximate production row counts.
  • Module-collision check (scripts/check_module_collisions.py) passes; config_schema.json and manifest.json validate as JSON; registry synced.

Not exercised in this environment: live NOAA fetch (host blocked by sandbox egress policy — parsing is unit-tested against the documented AWC response shape), real hardware, and the LEDMatrix emulator.

Required for plugin changes

  • Bumped version in manifest.json (1.10.0 → 1.11.0); registry synced
  • class_name matches (FlightTrackerPlugin, unchanged)
  • entry_point matches (manager.py, unchanged)
  • Updated the plugin's README.md (new Airport Weather section + config keys)
  • config_schema.json updated — new nested metar object with default/description/constraints for every option; metar added to the rotation_views enum + labels
  • Registry synced via update_registry.py (plugins.json → 1.11.0)

Notes for reviewer

  • NOTAMs are intentionally excluded. The user asked about them, but unlike the key-free METAR/TAF/PIREP/SIGMET endpoints, NOTAMs require the separate FAA NMS API with OAuth client_id/client_secret and token management, and are verbose on a small matrix. Left as a documented follow-up.
  • Design mirrors existing patterns: the metar view is a rotation slot like map/stats (runtime-only, not in manifest display_modes); weather fetches on their own slow cadence in update() (default 10 min, cached, gated on visibility) so they never slow the aircraft loop; on_config_change rebuilds the fetcher live. New module metar_fetcher.py is plugin-unique and imported at the top of manager.py, satisfying the cross-plugin module-collision rule.
  • SIGMET/AIRMET are region-based (not airport-specific); the page dedups a nationwide feed to the distinct active hazards with a total count.
  • Multi-airport support: the view rotates through each configured airport's pages.

🤖 Generated with Claude Code

https://claude.ai/code/session_012ka1E5TT1Ai9cuKV9j7g4C


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added an optional airport weather rotation view, including METAR, TAF, PIREP, and SIGMET.
    • Extended configuration to select specific airports, control what’s shown, and set update/page timing.
    • Improved weather rendering with unit support and dedicated weather typography for clearer, more legible cards.
  • Documentation

    • Updated plugin documentation and configuration schema with the new “Airport Weather (METAR/TAF)” view, NOAA weather option details, and example setup.

Adds an opt-in "metar" rotation view that shows aviation weather for
user-chosen airports using the free NOAA Aviation Weather Center API
(no API key). Per airport it rotates a color-coded decoded METAR card
(flight-category badge: VFR/MVFR/IFR/LIFR), a raw METAR page, and
optional TAF and PIREP pages, plus a trailing SIGMET/AIRMET page.

- New metar_fetcher.py: cache-first, serve-stale AWC client. METAR/TAF
  batched by ids; PIREP per-airport; SIGMET global. Never raises to the
  caller.
- manager.py: new rotation view + granular slot, config read in
  __init__/on_config_change, independent fetch cadence in update(),
  timed page-rotation display, and content gating so an empty/unfetched
  slot is skipped.
- renderer.py: decoded METAR card + raw/TAF/PIREP/SIGMET pages, adaptive
  to 64x32 / 128x32 / 128x64 / 256x32.
- config_schema.json: nested "metar" object; "metar" added to
  rotation_views. manifest bumped 1.10.0 -> 1.11.0; registry synced.
- Tests for normalization (hPa->inHg, ceiling), TAF batching/merge,
  serve-stale, PIREP, and SIGMET parsing.

NOTAMs are intentionally excluded (they require separate FAA OAuth
credentials, unlike the key-free weather endpoints).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ka1E5TT1Ai9cuKV9j7g4C
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fceaf017-4cb0-41e5-8e62-c211a70e26f7

📥 Commits

Reviewing files that changed from the base of the PR and between d7a5cb7 and 68bedc7.

📒 Files selected for processing (10)
  • plugins.json
  • plugins/ledmatrix-flights/README.md
  • plugins/ledmatrix-flights/assets/fonts/6x10.bdf
  • plugins/ledmatrix-flights/config_schema.json
  • plugins/ledmatrix-flights/manager.py
  • plugins/ledmatrix-flights/manifest.json
  • plugins/ledmatrix-flights/metar_fetcher.py
  • plugins/ledmatrix-flights/renderer.py
  • plugins/ledmatrix-flights/test/test_metar_fetcher.py
  • plugins/ledmatrix-flights/test/test_metar_render.py
✅ Files skipped from review due to trivial changes (2)
  • plugins.json
  • plugins/ledmatrix-flights/README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • plugins/ledmatrix-flights/config_schema.json
  • plugins/ledmatrix-flights/metar_fetcher.py

📝 Walkthrough

Walkthrough

Adds optional airport weather support to the ledmatrix-flights plugin, including NOAA AWC retrieval, METAR rotation configuration, weather rendering, incremental refresh integration, tests, documentation, and release metadata updates.

Changes

Airport Weather Feature

Layer / File(s) Summary
Weather configuration and documentation
plugins/ledmatrix-flights/config_schema.json, plugins/ledmatrix-flights/README.md
Adds the metar rotation view and configuration options, and documents weather pages, setup, units, and refresh behavior.
NOAA weather retrieval and normalization
plugins/ledmatrix-flights/metar_fetcher.py, plugins/ledmatrix-flights/test/test_metar_fetcher.py
Adds cache-backed NOAA AWC retrieval and normalization for METAR, TAF, PIREP, and SIGMET data, with tests for parsing, fallback, and configuration handling.
Weather card rendering
plugins/ledmatrix-flights/renderer.py, plugins/ledmatrix-flights/test/test_metar_render.py
Adds weather fonts, unit formatting, decoded METAR cards, raw weather pages, PIREP/SIGMET rendering, and renderer coverage across units and panel sizes.
Manager refresh and display integration
plugins/ledmatrix-flights/manager.py
Adds METAR configuration and airport resolution, incremental refresh work queues, display dispatch, page rotation, and content gating.
Release metadata and registry updates
plugins.json, plugins/ledmatrix-flights/manifest.json
Updates weather descriptions and tags, release metadata to version 1.12.2, changelog entries, and timestamps.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant FlightTrackerPlugin
  participant MetarFetcher
  participant NOAA_AWC_API
  participant FlightRenderer
  FlightTrackerPlugin->>MetarFetcher: service queued weather refresh
  MetarFetcher->>NOAA_AWC_API: fetch METAR, TAF, PIREP, and SIGMET data
  NOAA_AWC_API-->>MetarFetcher: return aviation weather payloads
  MetarFetcher-->>FlightTrackerPlugin: return normalized weather data
  FlightTrackerPlugin->>FlightRenderer: render selected weather page
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: optional airport weather support for Flight Tracker.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/flight-tracker-metar-taf-z1tjop

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codacy-production

codacy-production Bot commented Jul 9, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 234 complexity

Metric Results
Complexity 234

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

The weather view (METAR/TAF/PIREP/SIGMET) rendered in the plugin's blocky
PressStart2P + 4x6 fonts, which are hard to read for the long weather
strings at small panel sizes. Switch the weather cards to the cleaner,
more legible 5x7 face already used elsewhere in the project (elections,
masters, f1-scoreboard) and rendered normally (no pixel snapping) so it
reads like text.

- renderer.py: load a dedicated 5x7 head/body font for the weather view
  (sized to panel height) and use it in all weather render helpers; other
  views are unchanged.
- Bundle assets/fonts/5by7.regular.ttf in the plugin so the face resolves
  on-device (the core repo ships PressStart2P/4x6, not 5x7 — the other
  plugins that use 5x7 bundle their own copy too).
- manifest bumped 1.11.0 -> 1.11.1; registry synced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ka1E5TT1Ai9cuKV9j7g4C

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plugins/ledmatrix-flights/manager.py`:
- Around line 2324-2353: The METAR refresh path in `_refresh_metar_data()` is
still doing blocking network work inside `update()`, which can stall the
aircraft loop when cache entries expire or requests slow down. Refactor this
flow so the weather fetch is decoupled from the main update path—either move the
full refresh into a background worker/thread or split the per-airport
PIREP/SIGMET work across multiple cycles using the same kind of incremental
pattern used by `_background_fetch_fr24_details`. Keep `update()` limited to
scheduling work, and preserve the existing `_last_metar_fetch`,
`metar_update_interval`, and `self.metar_enabled` gating logic.
- Around line 312-323: FlightTrackerPlugin.__init__ currently calls
_apply_metar_config() unguarded, so a bad METAR setup can abort plugin
construction. Wrap that initialization in the same try/except pattern used by
on_config_change(), and on failure log the exception and leave the METAR feature
disabled while allowing the rest of the plugin to continue starting. Keep the
fix localized around _apply_metar_config and the METAR state fields initialized
in __init__.

In `@plugins/ledmatrix-flights/metar_fetcher.py`:
- Around line 41-57: Guard the `int()` conversion for `pirep_distance_nm` in
`MetarFetcher.__init__` the same way `update_interval_minutes` is handled, so a
malformed config value cannot raise during plugin setup. Wrap the cast in
`try/except (TypeError, ValueError)` with a safe default, and keep the fallback
behavior local to `MetarFetcher` since it is constructed unguarded from
`FlightTrackerPlugin.__init__` via `_apply_metar_config()`.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f77cc477-ce20-40d5-aae4-24171771cffc

📥 Commits

Reviewing files that changed from the base of the PR and between 4e5de3c and d7a5cb7.

⛔ Files ignored due to path filters (1)
  • plugins/ledmatrix-flights/assets/fonts/5by7.regular.ttf is excluded by !**/*.ttf
📒 Files selected for processing (8)
  • plugins.json
  • plugins/ledmatrix-flights/README.md
  • plugins/ledmatrix-flights/config_schema.json
  • plugins/ledmatrix-flights/manager.py
  • plugins/ledmatrix-flights/manifest.json
  • plugins/ledmatrix-flights/metar_fetcher.py
  • plugins/ledmatrix-flights/renderer.py
  • plugins/ledmatrix-flights/test/test_metar_fetcher.py

Comment thread plugins/ledmatrix-flights/manager.py
Comment thread plugins/ledmatrix-flights/manager.py
Comment thread plugins/ledmatrix-flights/metar_fetcher.py
claude added 4 commits July 9, 2026 17:12
Resolves the CodeRabbit review findings on the METAR feature:

- Perf: the weather refresh is now serviced incrementally — at most one
  HTTP request per update() cycle via a small work queue (_service_metar /
  _build_metar_work / _run_metar_step) — instead of doing METAR+TAF plus a
  PIREP call per airport plus SIGMET all in one cycle. A slow or failed
  weather request can no longer stall the aircraft loop for more than a
  single request. Preserves the _last_metar_fetch / metar_update_interval /
  enabled + visibility gating.
- Robustness: __init__ now guards _apply_metar_config() (like
  on_config_change already did) via a new _disable_metar() fallback, so a
  bad weather config only disables the feature instead of aborting plugin
  construction. on_config_change guards it separately too.
- Robustness: guard the pirep_distance_nm int() cast in MetarFetcher so a
  malformed config value falls back to the default rather than raising
  during construction (+ regression test).
- Docs: add docstrings to the new renderer/fetcher helpers (docstring
  coverage).

manifest bumped 1.11.1 -> 1.11.2; registry synced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ka1E5TT1Ai9cuKV9j7g4C
Two pilot-focused enhancements to the METAR view:

- Observation age: the decoded card shows how old the report is (e.g.
  "14m", "1h48"). When it's stale (older than ~75 min — a likely missed
  hourly update) the age turns amber with a "!" so old weather is never
  read as current. Uses the obsTime already in the fetched data; computed
  at render time, no extra fetch.
- Unit options: new metar.altimeter_unit (inhg|hpa), temp_unit (c|f),
  wind_unit (kt|mph|kmh|ms) and visibility_unit (sm|m|km) let weather
  display in US (A30.01 / 10SM / kt / degC) or international style
  (Q1013 / metres / etc.). Canonical values stay inHg/degC/kt/SM; the
  renderer converts for display, so the fetcher/cache are unchanged.

Adds test/test_metar_render.py (unit conversions + age formatting + all
panel sizes render). manifest bumped 1.11.2 -> 1.12.0; registry synced;
README documents both.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ka1E5TT1Ai9cuKV9j7g4C
The 5x7 weather text looked soft/blurry because the face anti-aliases at
every size (and was being drawn smoothed). Draw the weather cards in
1-bit "mono" mode (draw.fontmode = "1") so glyphs snap to the LED grid
with no anti-aliasing, and bump the size a little (13/9 on 32px-tall
panels, 16/12 on taller) so the small decoded fields and wrapped raw
METAR/TAF stay legible. Same bundled 5x7 font, no stretching; other
flight-tracker views are untouched.

manifest bumped 1.12.0 -> 1.12.1; registry synced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ka1E5TT1Ai9cuKV9j7g4C
Replace the soft, anti-aliased 5x7 TTF with the 6x10 bitmap (.bdf) font
from the LEDMatrix font set for the weather cards. FreeType renders a .bdf
pixel-exact at its native size (10px), so the METAR/TAF/PIREP/SIGMET text
is sharp on the LED grid with no anti-aliasing and no stretching blur.

- Bundle assets/fonts/6x10.bdf; drop the now-unused 5by7.regular.ttf.
- Load it via the existing font resolver at its fixed pixel size, with a
  fallback to the existing small font if a Pillow/FreeType build lacks BDF
  support (so font loading can never crash the plugin).
- Use a tight, measured line advance (the 6x10 cell is 10px but the inked
  glyphs are ~8px) so the decoded card still fits a header + two field rows
  on a 32px-tall panel; verified crisp and complete at 64x32 / 128x32 /
  128x64 / 256x32.

Other flight-tracker views are unchanged. manifest 1.12.1 -> 1.12.2;
registry synced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012ka1E5TT1Ai9cuKV9j7g4C
@ChuckBuilds ChuckBuilds merged commit baf4c8c into main Jul 10, 2026
4 checks passed
ChuckBuilds pushed a commit that referenced this pull request Jul 10, 2026
Resolves conflicts after #173 (phase-1 LICENSE) and #176 (flights
airport-weather) landed on main:
- ledmatrix-flights/manifest.json: main advanced to 1.12.2 (still MIT).
  Re-applied the GPL-3.0 license flip on top and bumped to 1.12.3,
  preserving the weather-feature version history.
- plugins.json: regenerated from manifests (deterministic).

flights -> 1.12.3, stocks -> 2.3.1 (both GPL-3.0).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F9Saiat9CQmNi3DeDdvacB
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