diff --git a/README.md b/README.md
index cd4e998f..8c02d2fd 100644
--- a/README.md
+++ b/README.md
@@ -163,7 +163,7 @@ curl -X POST http://your-pi-ip:5000/api/v3/plugins/install \
| Plugin | Description | Preview |
|--------|-------------|---------|
-| [Flight Tracker](./plugins/ledmatrix-flights/) | Real-time ADS-B aircraft tracking with map display | |
+| [Flight Tracker](./plugins/ledmatrix-flights/) | Real-time ADS-B aircraft tracking with map display |
|
| [Countdown Display](./plugins/countdown/) | Customizable countdowns for birthdays, events, holidays |
|
| [Election Results](./plugins/ledmatrix-elections/) | Live election results ticker with full-screen race interrupts | |
diff --git a/docs/assets/ledmatrix-flights/display-modes.png b/docs/assets/ledmatrix-flights/display-modes.png
new file mode 100644
index 00000000..1439965f
Binary files /dev/null and b/docs/assets/ledmatrix-flights/display-modes.png differ
diff --git a/docs/assets/ledmatrix-flights/hero.png b/docs/assets/ledmatrix-flights/hero.png
new file mode 100644
index 00000000..19a6da5c
Binary files /dev/null and b/docs/assets/ledmatrix-flights/hero.png differ
diff --git a/docs/assets/ledmatrix-flights/panel-sizes.png b/docs/assets/ledmatrix-flights/panel-sizes.png
new file mode 100644
index 00000000..73117f62
Binary files /dev/null and b/docs/assets/ledmatrix-flights/panel-sizes.png differ
diff --git a/docs/assets/ledmatrix-flights/shots.json b/docs/assets/ledmatrix-flights/shots.json
new file mode 100644
index 00000000..c715c789
--- /dev/null
+++ b/docs/assets/ledmatrix-flights/shots.json
@@ -0,0 +1,340 @@
+{
+ "plugin": "ledmatrix-flights",
+ "_comment": "Aircraft are seeded onto the plugin instance rather than fetched: the live source is a local SkyAware receiver. Positions are invented and placed within the default 10-mile radius of the schema's default centre. map_background is off in every shot because the basemap tiles come from a live tile server, so a render including them could not reproduce.",
+ "defaults": {
+ "width": 128,
+ "height": 32,
+ "scale": 6,
+ "freeze_time": "2026-09-03T15:30:00+00:00",
+ "skip_update": true,
+ "config": {
+ "enabled": true
+ },
+ "attrs": {
+ "aircraft_data": {
+ "A1B2C3": {
+ "icao": "A1B2C3",
+ "callsign": "DAL482",
+ "lat": 28.01,
+ "lon": -82.52,
+ "altitude": 34000,
+ "speed": 452,
+ "heading": 78,
+ "distance_miles": 4.2,
+ "origin": "TPA",
+ "destination": "ATL",
+ "aircraft_type": "B738",
+ "airline_icao": "DAL",
+ "vertical_rate": 0,
+ "last_seen": 1788449400.0,
+ "timestamp": 1788449400.0,
+ "color": [
+ 255,
+ 190,
+ 0
+ ]
+ },
+ "D4E5F6": {
+ "icao": "D4E5F6",
+ "callsign": "AAL119",
+ "lat": 27.905,
+ "lon": -82.398,
+ "altitude": 12500,
+ "speed": 310,
+ "heading": 190,
+ "distance_miles": 6.8,
+ "origin": "TPA",
+ "destination": "DFW",
+ "aircraft_type": "A321",
+ "airline_icao": "AAL",
+ "vertical_rate": 0,
+ "last_seen": 1788449400.0,
+ "timestamp": 1788449400.0,
+ "color": [
+ 90,
+ 200,
+ 255
+ ]
+ },
+ "07A8B9": {
+ "icao": "07A8B9",
+ "callsign": "SWA2210",
+ "lat": 27.972,
+ "lon": -82.56,
+ "altitude": 5200,
+ "speed": 265,
+ "heading": 341,
+ "distance_miles": 8.4,
+ "origin": "TPA",
+ "destination": "BNA",
+ "aircraft_type": "B737",
+ "airline_icao": "SWA",
+ "vertical_rate": 0,
+ "last_seen": 1788449400.0,
+ "timestamp": 1788449400.0,
+ "color": [
+ 255,
+ 120,
+ 120
+ ]
+ },
+ "C0D1E2": {
+ "icao": "C0D1E2",
+ "callsign": "JBU765",
+ "lat": 27.93,
+ "lon": -82.43,
+ "altitude": 2100,
+ "speed": 190,
+ "heading": 265,
+ "distance_miles": 2.9,
+ "origin": "TPA",
+ "destination": "JFK",
+ "aircraft_type": "A320",
+ "airline_icao": "JBU",
+ "vertical_rate": 0,
+ "last_seen": 1788449400.0,
+ "timestamp": 1788449400.0,
+ "color": [
+ 140,
+ 255,
+ 140
+ ]
+ }
+ }
+ }
+ },
+ "shots": [
+ {
+ "name": "hero",
+ "config": {
+ "enabled": true,
+ "display_mode": "overhead",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "mode-overhead",
+ "standalone": false,
+ "config": {
+ "enabled": true,
+ "display_mode": "overhead",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "mode-map",
+ "standalone": false,
+ "config": {
+ "enabled": true,
+ "display_mode": "map",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "mode-stats",
+ "standalone": false,
+ "config": {
+ "enabled": true,
+ "display_mode": "stats",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "mode-area",
+ "standalone": false,
+ "config": {
+ "enabled": true,
+ "display_mode": "area",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "units-imperial",
+ "standalone": false,
+ "width": 256,
+ "config": {
+ "enabled": true,
+ "display_mode": "overhead",
+ "units": "imperial",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "units-metric",
+ "standalone": false,
+ "width": 256,
+ "config": {
+ "enabled": true,
+ "display_mode": "overhead",
+ "units": "metric",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "track-deg",
+ "standalone": false,
+ "width": 256,
+ "config": {
+ "enabled": true,
+ "display_mode": "overhead",
+ "track_format": "deg",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "track-cardinal",
+ "standalone": false,
+ "width": 256,
+ "config": {
+ "enabled": true,
+ "display_mode": "overhead",
+ "track_format": "cardinal",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "size-64x32",
+ "width": 64,
+ "standalone": false,
+ "config": {
+ "enabled": true,
+ "display_mode": "overhead",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "size-128x32",
+ "width": 128,
+ "standalone": false,
+ "config": {
+ "enabled": true,
+ "display_mode": "overhead",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "size-128x64",
+ "width": 128,
+ "height": 64,
+ "standalone": false,
+ "config": {
+ "enabled": true,
+ "display_mode": "overhead",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ },
+ {
+ "name": "size-256x32",
+ "width": 256,
+ "standalone": false,
+ "config": {
+ "enabled": true,
+ "display_mode": "overhead",
+ "map_background": {
+ "enabled": false
+ }
+ }
+ }
+ ],
+ "composites": [
+ {
+ "name": "display-modes",
+ "columns": 1,
+ "cells": [
+ {
+ "shot": "mode-overhead",
+ "label": "display_mode: overhead",
+ "sublabel": "one aircraft at a time, in detail"
+ },
+ {
+ "shot": "mode-map",
+ "label": "display_mode: map",
+ "sublabel": "positions plotted around you"
+ },
+ {
+ "shot": "mode-stats",
+ "label": "display_mode: stats"
+ },
+ {
+ "shot": "mode-area",
+ "label": "display_mode: area"
+ }
+ ]
+ },
+ {
+ "name": "units",
+ "columns": 1,
+ "cells": [
+ {
+ "shot": "units-imperial",
+ "label": "units: imperial",
+ "sublabel": "feet and knots"
+ },
+ {
+ "shot": "units-metric",
+ "label": "units: metric"
+ }
+ ]
+ },
+ {
+ "name": "track-format",
+ "columns": 1,
+ "cells": [
+ {
+ "shot": "track-deg",
+ "label": "track_format: deg"
+ },
+ {
+ "shot": "track-cardinal",
+ "label": "track_format: cardinal"
+ }
+ ]
+ },
+ {
+ "name": "panel-sizes",
+ "columns": 2,
+ "cells": [
+ {
+ "shot": "size-64x32",
+ "label": "64 x 32"
+ },
+ {
+ "shot": "size-128x32",
+ "label": "128 x 32"
+ },
+ {
+ "shot": "size-128x64",
+ "label": "128 x 64"
+ },
+ {
+ "shot": "size-256x32",
+ "label": "256 x 32"
+ }
+ ]
+ }
+ ]
+}
diff --git a/docs/assets/ledmatrix-flights/track-format.png b/docs/assets/ledmatrix-flights/track-format.png
new file mode 100644
index 00000000..0adca08a
Binary files /dev/null and b/docs/assets/ledmatrix-flights/track-format.png differ
diff --git a/docs/assets/ledmatrix-flights/units.png b/docs/assets/ledmatrix-flights/units.png
new file mode 100644
index 00000000..1e5a2325
Binary files /dev/null and b/docs/assets/ledmatrix-flights/units.png differ
diff --git a/plugins.json b/plugins.json
index 2dc509a1..d2e09b71 100644
--- a/plugins.json
+++ b/plugins.json
@@ -436,10 +436,10 @@
"plugin_path": "plugins/ledmatrix-flights",
"stars": 0,
"downloads": 0,
- "last_updated": "2026-08-03",
+ "last_updated": "2026-09-03",
"verified": true,
"screenshot": "",
- "latest_version": "1.12.18"
+ "latest_version": "1.12.19"
},
{
"id": "march-madness",
diff --git a/plugins/ledmatrix-flights/README.md b/plugins/ledmatrix-flights/README.md
index 013c7be2..06f0b64b 100644
--- a/plugins/ledmatrix-flights/README.md
+++ b/plugins/ledmatrix-flights/README.md
@@ -13,6 +13,13 @@
# LEDMatrix Flight Tracker Plugin
+
+
+*Every image in this README is real plugin output, rendered at the true panel
+size from seeded aircraft so it reproduces exactly. Positions and callsigns are
+invented.*
+
Real-time aircraft tracking plugin for LEDMatrix with ADS-B data, map backgrounds, flight plans, and proximity alerts.
## Features
@@ -97,17 +104,205 @@ Add FlightAware API key to `config/config_secrets.json`:
**Note:** The plugin will work without an API key for basic aircraft tracking, but flight plan features (origin/destination) will be disabled.
-### Full Configuration Options
+### Full configuration options
+
+Settings live in the plugin's tab in the web UI and in `config/config.json`
+under `ledmatrix-flights`. The full schema is
+[`config_schema.json`](config_schema.json).
+
+### Source and polling
+
+| Key | Default | Notes |
+|---|---|---|
+| `enabled` | `false` | Enable or disable the flight tracker plugin. |
+| `data_source` | `"skyaware"` | Where to get live aircraft position data. Choose one setup path: (1) Local receiver — 'skyaware': requires a PiAware/dump1090 ADS-B receiver on your network, most accurate data. (2) Free cloud — 'adsbfi': free global ADS-B feed from adsb.fi, no account or hardware needed. 'adsblol': same idea via adsb.lol. Both free cloud options work worldwide with no sign-up — one of `skyaware`, `adsbfi`, `adsblol`. |
+| `skyaware_url` | `"http://192.168.86.30/skyaware/data/aircraf…` | URL to your local ADS-B receiver's aircraft.json endpoint. Only used when data_source is 'skyaware'. Change this to match your receiver's IP address. |
+| `update_interval` | `5` | Interval in seconds between aircraft data updates (1–300). |
+| `live_update_interval` | `2` | Faster fetch interval (seconds) used while a flight is locked on for the overhead view, so altitude/distance update smoothly. The ADS-B source is ~1Hz, so a low value is safe. Idle fetches use update_interval (1–60). Advanced. |
+| `live_priority` | `false` | When enabled, an aircraft entering the proximity radius immediately preempts the normal rotation to show the overhead view for the proximity alert window (see proximity_alert.duration_seconds). Adds a 'flight_tracker_live' rotation slot that stays blank/skipped until a plane is overhead. Leave off for legacy behavior. Advanced. |
+| `display_duration` | `30` | How long to show the flight tracker display (10-300 seconds). |
+| `flight_records` | — | Track all-time closest and farthest flights ever seen, shown as extra stats rotation slots. |
+| `fr24_enrichment` | `true` | Fetch origin/destination and aircraft type for free in the background using FlightRadar24 data. Works with all data sources. This is the recommended free alternative to a paid FlightAware API key — leave enabled unless you have a specific reason to turn it off. Advanced. |
+| `fr24_enrichment_interval` | `60` | How often to refresh free FR24 route data in the background. Applies when fr24_enrichment is enabled (30–600). Advanced. |
+| `enrichment_provider` | `"adsbnet"` | Fallback source for origin/destination data not covered by FR24 enrichment. 'adsbnet': free route lookups via adsb.lol — good coverage for major airlines, no account needed (recommended). 'flightaware': paid FlightAware AeroAPI — highest coverage but requires a paid subscription configured in the FlightAware section below — one of `adsbnet`, `flightaware`. Advanced. |
+| `route_cache_ttl` | `300` | How long to cache flight route enrichment data (60–3600). Advanced. |
+| `flight_records.enabled` | `true` | Track and display all-time closest and farthest flights (persisted across restarts). |
+
+### Where you are, and what counts as nearby
+
+| Key | Default | Notes |
+|---|---|---|
+| `center_latitude` | `27.9506` | Center latitude for the map display (-90–90). |
+| `center_longitude` | `-82.4572` | Center longitude for the map display (-180–180). |
+| `map_radius_miles` | `10` | Radius in miles to display around center point (1–100). |
+| `zoom_factor` | `1.0` | Zoom factor to use more of the display (1.0 = normal, higher = more zoomed in) (0.5–5.0). Advanced. |
+| `max_aircraft` | `5` | Maximum aircraft to display per page in area mode (1–20). Advanced. |
+| `min_altitude_ft` | `0` | Minimum altitude in feet for area mode filtering. Set to 0 to disable. Advanced. |
+| `max_altitude_ft` | `0` | Maximum altitude in feet for area mode filtering. Set to 0 to disable. Advanced. |
+| `aircraft_categories` | *(empty)* | ICAO aircraft categories to display (e.g. A1, A2, A3). Empty list shows all. Advanced. |
+| `tracked_flights` | *(empty)* | Flight numbers, callsigns, or tail numbers to track specifically (max 3). E.g. ["AA123", "N12345"]. |
+| `anchor_airport` | *(blank)* | ICAO or IATA airport code to prioritize in area mode (e.g. KTPA or TPA). Arrivals/departures shown first. |
+
+### Display mode and layout
+
+| Key | Default | Notes |
+|---|---|---|
+| `display_mode` | `"auto"` | Single-view display mode, used only when 'rotation_views' is not set. 'area' shows multi-aircraft list with FlightWall metrics. 'flight_tracking' shows tracked flight details. 'auto' chooses based on context — one of `map`, `overhead`, `stats`, `area`, `flight_tracking`, `auto`. |
+| `rotation_views` | — | Which views the display rotation cycles through. Each selected view gets its own rotation slot and an empty/no-content slot is skipped. Leave all unchecked to show nothing in the normal rotation — useful for an overhead-only board (pair with Overhead Live Priority). When this field is omitted entirely, the single 'Display Mode' setting is used instead (legacy behavior). The overhead view is not listed here; it is driven by live_priority + proximity_alert. |
+| `layout` | *(blank)* | Force a specific flight detail layout. Leave empty for auto-selection based on display width — one of `""`, `flight_detail_wide`, `flight_detail_condensed`. Advanced. |
+| `widescreen_threshold` | `256` | Minimum canvas width in pixels to use the widescreen flight detail layout (128–1280). Advanced. |
+| `show_banner` | `false` | Show a 'FLIGHTS' banner for 2 seconds at the start of each display slot. Advanced. |
+| `show_aircraft_icon` | `true` | Show airline logos in area mode (8×8 pixel sprites next to callsigns). Flight detail layouts always show logos in the logo zone when available (52 airlines included as PNG assets). Advanced. |
+| `show_trails` | `true` | Show aircraft movement trails. Advanced. |
+| `trail_length` | `10` | Number of trail points to display per aircraft (0–50). Advanced. |
+| `scroll_speed` | `2` | Scroll speed in pixels per frame for long text (1–10). Advanced. |
+| `overhead_alt_interval` | `4` | On the overhead (live-priority) card, the route (e.g. SEA>PHX) and the aircraft model share one text row and alternate. This is how many seconds each stays up before swapping. Set to 0 to disable alternation (route always wins). The model is shown as a friendly name (e.g. 'Boeing 737-900') when the type is known. Advanced. |
+
+### Units and formatting
+
+| Key | Default | Notes |
+|---|---|---|
+| `units` | `"imperial"` | Legacy unit system toggle. For finer control use the per-metric options below — one of `imperial`, `metric`. |
+| `altitude_unit` | `"ft"` | Altitude display unit — one of `ft`, `m`, `km`, `nmi`. Advanced. |
+| `speed_unit` | `"kn"` | Speed display unit — one of `kn`, `mph`, `kmh`, `ms`, `mach`. Advanced. |
+| `track_format` | `"deg"` | Track/heading display format. 'deg' = numeric degrees (090deg), 'cardinal' = compass point (E) — one of `deg`, `cardinal`. Advanced. |
+| `vr_unit` | `"fpm"` | Vertical rate display unit — one of `fpm`, `fts`, `ms`, `mph`, `kmh`. Advanced. |
+
+### Colours
+
+| Key | Default | Notes |
+|---|---|---|
+| `header_color` | `[255, 200, 0]` | RGB color for headers/callsigns in area and flight tracking modes. Advanced. |
+| `metric_color` | `[255, 255, 255]` | RGB color for metric values (alt, speed, etc.) in area and flight tracking modes. Advanced. |
+| `error_color` | `[255, 0, 0]` | RGB color for error/no-data messages. Advanced. |
+| `airport_color` | `[0, 120, 255]` | RGB color for airport full names in widescreen layout. Advanced. |
+
+### Offline aircraft database
+
+| Key | Default | Notes |
+|---|---|---|
+| `use_offline_database` | `true` | Use offline aircraft database for aircraft type lookups. |
+| `offline_database_auto_update` | `true` | Automatically update offline database. |
+| `offline_database_update_interval_days` | `30` | Interval in days between offline database updates (1–365). |
+
+### Map background
+
+| Key | Default | Notes |
+|---|---|---|
+| `map_background.enabled` | `true` | Enable map background tiles. |
+| `map_background.tile_provider` | `"carto_dark"` | Map tile provider — one of `osm`, `carto`, `carto_dark`, `stamen`, `esri`. |
+| `map_background.tile_size` | `256` | Tile size in pixels. Advanced. |
+| `map_background.cache_ttl_hours` | `8760` | Tile cache time-to-live in hours (1–8760). Advanced. |
+| `map_background.fade_intensity` | `0.4` | Fade intensity for map background (0.0-1.0). Advanced. |
+| `map_background.brightness` | `1.0` | Brightness adjustment for map (0.0-2.0). Advanced. |
+| `map_background.contrast` | `1.0` | Contrast adjustment for map (0.0-2.0). Advanced. |
+| `map_background.saturation` | `1.0` | Saturation adjustment for map (0.0-2.0). Advanced. |
+| `map_background.disable_on_cache_error` | `false` | Disable map background if cache errors occur. Advanced. |
+| `map_background.custom_tile_server` | `"https://maps.chuck-builds.com"` | Custom tile server URL (optional, for self-hosted OSM servers). When set, this overrides the tile_provider setting. Leave empty to use the tile_provider setting instead. Advanced. |
+
+### Airport weather
+
+| Key | Default | Notes |
+|---|---|---|
+| `metar.enabled` | `false` | Fetch and display METAR/TAF/PIREP/SIGMET for the airports below. |
+| `metar.airports` | *(empty)* | ICAO (e.g. KTPA) or IATA (e.g. TPA) airport codes. The display rotates through each airport's weather. Example: ["KTPA", "KJFK"]. |
+| `metar.show_taf` | `true` | Show the terminal aerodrome forecast (raw) on a page after each airport's METAR. |
+| `metar.show_raw` | `true` | Show the raw METAR string on its own page in addition to the decoded card. |
+| `metar.show_pirep` | `false` | Show recent pilot reports near each airport. Advanced. |
+| `metar.show_sigmet` | `false` | Show active domestic SIGMET/AIRMET advisories (region-based, not airport-specific). Advanced. |
+| `metar.pirep_distance_nm` | `200` | How far from each airport to search for pilot reports (25–500). Advanced. |
+| `metar.update_interval_minutes` | `10` | How often to refresh weather from NOAA. METARs update roughly hourly, so 10 minutes is plenty (5–120). Advanced. |
+| `metar.page_duration_seconds` | `8` | How long each weather page (decoded METAR, raw, TAF, etc.) is shown before advancing (3–60). Advanced. |
+| `metar.altimeter_unit` | `"inhg"` | Altimeter setting display: 'inhg' shows US style (A30.01), 'hpa' shows international style (Q1016) — one of `inhg`, `hpa`. Advanced. |
+| `metar.temp_unit` | `"c"` | Temperature/dewpoint unit on the decoded card — one of `c`, `f`. Advanced. |
+| `metar.wind_unit` | `"kt"` | Wind speed unit. Aviation standard is knots (kt) — one of `kt`, `mph`, `kmh`, `ms`. Advanced. |
+| `metar.visibility_unit` | `"sm"` | Visibility unit: statute miles (US), metres or kilometres (international) — one of `sm`, `m`, `km`. Advanced. |
+
+### Proximity alert
+
+| Key | Default | Notes |
+|---|---|---|
+| `proximity_alert.enabled` | `true` | Enable proximity alerts. |
+| `proximity_alert.distance_miles` | `0.1` | Distance threshold in miles for proximity alert (0.01–10.0). |
+| `proximity_alert.duration_seconds` | `30` | Hard cap (seconds) on how long a single overhead flight holds the screen, measured from when it is locked on. The flight shows for this long even if it leaves the radius sooner, and is released after this even if it lingers (5–300). Advanced. |
+| `proximity_alert.cooldown_seconds` | `30` | After a flight's window ends, suppress the overhead preempt for this many seconds so the normal rotation (weather/clock/sports) gets guaranteed screen time, even if planes remain overhead. Set to 0 to disable the cooldown (0–600). Advanced. |
+
+### Fonts
+
+| Key | Default | Notes |
+|---|---|---|
+| `fonts.large_size` | `0` | Override size for the large font tier. 0 = auto (0–32). Advanced. |
+| `fonts.medium_size` | `0` | Override size for the medium font tier. 0 = auto (0–32). Advanced. |
+| `fonts.small_size` | `0` | Override size for the small font tier. 0 = auto (0–32). Advanced. |
+
+### FlightAware / OpenSky
+
+| Key | Default | Notes |
+|---|---|---|
+| `flightaware.api_key` | *(blank)* | Your FlightAware AeroAPI key. Leave blank if you are not using FlightAware — the plugin works fully without this. Secret, masked in the web UI. |
+| `flightaware.enabled` | `false` | Enable paid FlightAware API calls. Must be true AND api_key must be set for FlightAware to be used. Disabled by default — do not enable unless you have a paid subscription. |
+| `flightaware.max_api_calls_per_hour` | `25` | Maximum FlightAware API calls per hour (1–100). Advanced. |
+| `flightaware.daily_api_budget` | `60` | Maximum FlightAware API calls per day (1–200). Advanced. |
+| `flightaware.cache_ttl_hours` | `12` | Flight plan cache time-to-live in hours (1–168). Advanced. |
+| `flightaware.min_callsign_length` | `4` | Minimum callsign length to fetch flight plan data (3–10). Advanced. |
+| `flightaware.airline_callsign_prefixes` | `["AAL", "UAL", "DAL", "SWA", "JBU", "ASQ", …` | List of airline callsign prefixes to prioritize for flight plan fetching. Advanced. |
+| `flightaware.background_service` | — | Background service configuration for fetching flight plan data without blocking the display. |
+
+### Background service
+
+| Key | Default | Notes |
+|---|---|---|
+| `background_service.enabled` | `true` | . |
+| `background_service.fetch_interval_hours` | `4` | . Advanced. |
+| `background_service.max_calls_per_run` | `10` | . Advanced. |
+
+The FlightAware block has its own background-service settings, separate from
+the top-level `background_service`:
+
+| Key | Default | Notes |
+|---|---|---|
+| `flightaware.background_service.enabled` | `true` | Enable the background service for flight plan fetching. |
+| `flightaware.background_service.fetch_interval_hours` | `4` | Interval in hours between background fetch runs (1–168). Advanced. |
+| `flightaware.background_service.max_calls_per_run` | `10` | Maximum number of flight plan calls fetched per background run (1–100). Advanced. |
+
+### Legacy flat API keys
+
+The plugin accepts the FlightAware and OpenSky credentials either nested under
+`flightaware` (above) or as flat top-level keys. `_normalize_flightaware_config()`
+copies the nested form onto the flat names once at start-up, so both work and
+you only need to set one.
+
+
+| Key | Default | Notes |
+|---|---|---|
+| `opensky_username` | *(blank)* | OpenSky Network username. Only needed if you have manually set enrichment_provider to 'opensky' via direct config edit. Leave blank for the standard free setup. Secret, masked in the web UI. Advanced. |
+| `opensky_password` | *(blank)* | OpenSky Network password. Only needed alongside opensky_username above. Secret, masked in the web UI. Advanced. |
+| `flightaware_api_key` | *(blank)* | Deprecated — use the FlightAware section above instead. Kept only for backward compatibility with older configs. Secret, masked in the web UI. Advanced. |
+| `flight_plan_enabled` | `false` | Deprecated: moved to FlightAware section. Advanced. |
+| `max_api_calls_per_hour` | `25` | Deprecated: moved to FlightAware section. Advanced. |
+| `daily_api_budget` | `60` | Deprecated: moved to FlightAware section. Advanced. |
+| `flight_plan_cache_ttl_hours` | `12` | Deprecated: moved to FlightAware section. Advanced. |
+| `min_callsign_length` | `4` | Deprecated: moved to FlightAware section. Advanced. |
+| `airline_callsign_prefixes` | *(empty)* | Deprecated: moved to FlightAware section. Advanced. |
-See `config_schema.json` for complete configuration options including:
-- Map background settings (tile provider, brightness, contrast, saturation)
-- Proximity alert configuration
-- Flight plan fetching settings
-- Background service configuration
-- Offline database settings
## Display Modes
+
+
+`map` is shown here with `map_background.enabled` off. With it on, the aircraft
+are plotted over basemap tiles fetched from a tile server — that is why this
+one screen cannot be reproduced offline the way the others are.
+
+Units and heading format apply across the modes:
+
+
+
+
+
+
+
+
### Map Mode (`display_mode: "map"`)
Shows a geographic map with:
diff --git a/plugins/ledmatrix-flights/manager.py b/plugins/ledmatrix-flights/manager.py
index 237b0267..ca513d50 100644
--- a/plugins/ledmatrix-flights/manager.py
+++ b/plugins/ledmatrix-flights/manager.py
@@ -3200,8 +3200,11 @@ def _render_map_image(self) -> Image.Image:
continue
x, y = pixel
- # Brighten the plane colors by boosting RGB values
- base_color = aircraft['color']
+ # Brighten the plane colors by boosting RGB values.
+ # Every other read of this field uses .get with a fallback; a record
+ # that reached the map without one took the whole mode to ERR: map
+ # while the other modes rendered it fine.
+ base_color = aircraft.get('color') or (255, 255, 255)
color = tuple(min(255, int(c * 1.3)) for c in base_color)
# Draw single pixel for each aircraft
diff --git a/plugins/ledmatrix-flights/manifest.json b/plugins/ledmatrix-flights/manifest.json
index b0196b80..37154315 100644
--- a/plugins/ledmatrix-flights/manifest.json
+++ b/plugins/ledmatrix-flights/manifest.json
@@ -1,7 +1,7 @@
{
"id": "ledmatrix-flights",
"name": "Flight Tracker",
- "version": "1.12.18",
+ "version": "1.12.19",
"description": "Real-time aircraft tracking with ADS-B/FlightRadar24/OpenSky/adsb.fi/adsb.lol data, map backgrounds, area mode, flight tracking, anchor airport, flight records, and optional airport weather (METAR/TAF/PIREP/SIGMET via the free NOAA Aviation Weather Center API)",
"author": "ChuckBuilds",
"entry_point": "manager.py",
@@ -37,6 +37,12 @@
"min_ledmatrix_version": "2.0.0",
"max_ledmatrix_version": "3.0.0",
"versions": [
+ {
+ "version": "1.12.19",
+ "released": "2026-09-03",
+ "notes": "Documentation, and one map-mode robustness fix. The README's 'Full Configuration Options' section pointed at the schema file instead of listing anything; 84 of the 96 settings were never named. All 96 are now documented by key, grouped by area. Adds real rendered screenshots of the four display modes, both unit systems, both heading formats and four panel sizes. Map mode read aircraft['color'] with a hard subscript where every other read of that field uses .get with a fallback, so a record arriving without one took the whole mode to 'ERR: map' while the other modes rendered it; it now falls back.",
+ "ledmatrix_min_version": "2.0.0"
+ },
{
"version": "1.12.18",
"released": "2026-08-26",
@@ -246,5 +252,5 @@
"ledmatrix_min_version": "2.0.0"
}
],
- "last_updated": "2026-08-03"
+ "last_updated": "2026-09-03"
}