Plane radar pr #329

Open
havedill wants to merge 3 commits from havedill/plane-radar-pr into dev
havedill commented 2026-06-23 09:54:22 +00:00 (Migrated from github.com)

Summary

Adds a Plane Radar widget that shows live nearby aircraft on the center orb and detail views on the other four orbs. Inspired by ESP32-Plane-Radar.

  • Orb 0: Radar view with range rings, aircraft positions, heading triangles, speed vectors, and beyond-range edge dots
  • Orbs 1–4: Closest aircraft detail (callsign, type, route, speed, altitude, arriving/departing hint, military/PIA/LADD flags)
  • OK button: Cycles radar range (5 / 10 / 15 / 25 mi ring presets); selection is saved in NVS
  • Incremental redraws: Refreshes without full-screen flash; detail orbs stay pinned to the same aircraft between polls
    Data sources (no API keys required):
  • ADS-B: adsb.fi opendata API
  • Routes: adsbdb.com
    Disabled by default (WIDGET_OFF) so existing builds are unchanged.

Configuration (config.h)

Add to your config.h (see config.h.template):
#define INCLUDE_PLANE_RADAR WIDGET_ON // WIDGET_ON | WIDGET_OFF | WIDGET_DISABLED
Optional overrides (defaults in config.system.h):

Define Default Description
PLANE_RADAR_LAT 48.4284 Radar center latitude
PLANE_RADAR_LON -123.3656 Radar center longitude
PLANE_RADAR_RANGE_INDEX 1 Initial range preset: 0=5 mi, 1=10 mi, 2=15 mi, 3=25 mi (inner ring label)
PLANE_RADAR_FETCH_INTERVAL_SEC 3 ADS-B poll interval (seconds)
PLANE_RADAR_CYCLE_DELAY 180 Seconds to stay on Plane Radar before widget carousel advances
PLANE_RADAR_UNITS_METRIC (undefined) Define to show range label in km; omit for miles
Example:
#define INCLUDE_PLANE_RADAR WIDGET_ON
#define PLANE_RADAR_LAT 45.4215
#define PLANE_RADAR_LON -75.6972
#define PLANE_RADAR_RANGE_INDEX 1
#define PLANE_RADAR_FETCH_INTERVAL_SEC 5
#define PLANE_RADAR_CYCLE_DELAY 180
// #define PLANE_RADAR_UNITS_METRIC
Most settings can also be changed in the web UI when web-based config is enabled (planeLat, planeLon, planeFetchSec, planeCycleSec, planeUnitsMetric, enable/disable).
## Summary Adds a **Plane Radar** widget that shows live nearby aircraft on the center orb and detail views on the other four orbs. Inspired by [ESP32-Plane-Radar](https://github.com/MatixYo/ESP32-Plane-Radar). - **Orb 0:** Radar view with range rings, aircraft positions, heading triangles, speed vectors, and beyond-range edge dots - **Orbs 1–4:** Closest aircraft detail (callsign, type, route, speed, altitude, arriving/departing hint, military/PIA/LADD flags) - **OK button:** Cycles radar range (5 / 10 / 15 / 25 mi ring presets); selection is saved in NVS - **Incremental redraws:** Refreshes without full-screen flash; detail orbs stay pinned to the same aircraft between polls **Data sources (no API keys required):** - ADS-B: [adsb.fi opendata API](https://opendata.adsb.fi/) - Routes: [adsbdb.com](https://api.adsbdb.com/) Disabled by default (`WIDGET_OFF`) so existing builds are unchanged. --- ## Configuration (`config.h`) Add to your `config.h` (see `config.h.template`): #define INCLUDE_PLANE_RADAR WIDGET_ON // WIDGET_ON | WIDGET_OFF | WIDGET_DISABLED Optional overrides (defaults in `config.system.h`): | Define | Default | Description | |--------|---------|-------------| | `PLANE_RADAR_LAT` | `48.4284` | Radar center latitude | | `PLANE_RADAR_LON` | `-123.3656` | Radar center longitude | | `PLANE_RADAR_RANGE_INDEX` | `1` | Initial range preset: `0`=5 mi, `1`=10 mi, `2`=15 mi, `3`=25 mi (inner ring label) | | `PLANE_RADAR_FETCH_INTERVAL_SEC` | `3` | ADS-B poll interval (seconds) | | `PLANE_RADAR_CYCLE_DELAY` | `180` | Seconds to stay on Plane Radar before widget carousel advances | | `PLANE_RADAR_UNITS_METRIC` | (undefined) | Define to show range label in km; omit for miles | Example: #define INCLUDE_PLANE_RADAR WIDGET_ON #define PLANE_RADAR_LAT 45.4215 #define PLANE_RADAR_LON -75.6972 #define PLANE_RADAR_RANGE_INDEX 1 #define PLANE_RADAR_FETCH_INTERVAL_SEC 5 #define PLANE_RADAR_CYCLE_DELAY 180 // #define PLANE_RADAR_UNITS_METRIC Most settings can also be changed in the **web UI** when web-based config is enabled (`planeLat`, `planeLon`, `planeFetchSec`, `planeCycleSec`, `planeUnitsMetric`, enable/disable).
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2026-07-16 00:47:08 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull request overview

Adds a new Plane Radar widget to the firmware widget carousel, fetching live nearby aircraft via ADS-B and enriching details with route lookups, with optional per-widget carousel cycle timing.

Changes:

  • Introduces PlaneRadarWidget (radar center orb + detail orbs), including range cycling persisted to NVS.
  • Adds ADS-B (AdsbClient) and route (RouteClient) HTTP clients with lightweight caching/prefetch.
  • Extends the widget framework to support a per-widget cycle delay override, and wires the new widget into main.cpp plus configuration defaults/templates.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
firmware/src/widgets/planeradarwidget/RouteClient.h Declares route lookup + cache interface.
firmware/src/widgets/planeradarwidget/RouteClient.cpp Implements callsign normalization, caching, and adsbdb route fetch/prefetch.
firmware/src/widgets/planeradarwidget/PlaneRadarWidget.h Declares the Plane Radar widget, state, and drawing/update helpers.
firmware/src/widgets/planeradarwidget/PlaneRadarWidget.cpp Implements radar rendering, detail screens, range cycling, NVS persistence, and route refresh integration.
firmware/src/widgets/planeradarwidget/AdsbClient.h Declares ADS-B fetch API and aircraft model.
firmware/src/widgets/planeradarwidget/AdsbClient.cpp Implements ADS-B fetch + JSON parsing into a fixed-size aircraft list.
firmware/src/main.cpp Registers Plane Radar widget behind INCLUDE_PLANE_RADAR != WIDGET_DISABLED.
firmware/src/core/widget/Widget.h Adds getWidgetCyclePageDelayMs() optional override hook.
firmware/src/core/utils/MainHelper.cpp Uses per-widget cycle delay override when advancing the widget carousel.
firmware/config/config.system.h Adds default macros for enabling/configuring Plane Radar.
firmware/config/config.h.template Documents Plane Radar config knobs and enables include toggle.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

## Pull request overview Adds a new **Plane Radar** widget to the firmware widget carousel, fetching live nearby aircraft via ADS-B and enriching details with route lookups, with optional per-widget carousel cycle timing. **Changes:** - Introduces `PlaneRadarWidget` (radar center orb + detail orbs), including range cycling persisted to NVS. - Adds ADS-B (`AdsbClient`) and route (`RouteClient`) HTTP clients with lightweight caching/prefetch. - Extends the widget framework to support a **per-widget cycle delay override**, and wires the new widget into `main.cpp` plus configuration defaults/templates. ### Reviewed changes Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | firmware/src/widgets/planeradarwidget/RouteClient.h | Declares route lookup + cache interface. | | firmware/src/widgets/planeradarwidget/RouteClient.cpp | Implements callsign normalization, caching, and adsbdb route fetch/prefetch. | | firmware/src/widgets/planeradarwidget/PlaneRadarWidget.h | Declares the Plane Radar widget, state, and drawing/update helpers. | | firmware/src/widgets/planeradarwidget/PlaneRadarWidget.cpp | Implements radar rendering, detail screens, range cycling, NVS persistence, and route refresh integration. | | firmware/src/widgets/planeradarwidget/AdsbClient.h | Declares ADS-B fetch API and aircraft model. | | firmware/src/widgets/planeradarwidget/AdsbClient.cpp | Implements ADS-B fetch + JSON parsing into a fixed-size aircraft list. | | firmware/src/main.cpp | Registers Plane Radar widget behind `INCLUDE_PLANE_RADAR != WIDGET_DISABLED`. | | firmware/src/core/widget/Widget.h | Adds `getWidgetCyclePageDelayMs()` optional override hook. | | firmware/src/core/utils/MainHelper.cpp | Uses per-widget cycle delay override when advancing the widget carousel. | | firmware/config/config.system.h | Adds default macros for enabling/configuring Plane Radar. | | firmware/config/config.h.template | Documents Plane Radar config knobs and enables include toggle. | </details> --- 💡 <a href="/brettdottech/info-orbs/new/dev?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
@ -0,0 +220,4 @@
s_aircraft[n].lat = plane["lat"].as<float>();
s_aircraft[n].lon = plane["lon"].as<float>();
s_aircraft[n].noseDeg = pickNoseHeading(plane);
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-07-16 00:47:08 +00:00

The lat/lon presence check is too strict: it only accepts values where plane["lat"]/plane["lon"] are is(). ArduinoJson commonly stores numbers as double/int, so valid aircraft can be skipped. You already have readJsonFloat() for this.

The lat/lon presence check is too strict: it only accepts values where plane["lat"]/plane["lon"] are is<float>(). ArduinoJson commonly stores numbers as double/int, so valid aircraft can be skipped. You already have readJsonFloat() for this.
@ -0,0 +190,4 @@
*dxKm = static_cast<float>(lon - centerLon) * kKmPerDeg;
*dyKm = static_cast<float>(lat - centerLat) * kKmPerDeg;
*distKm = sqrtf((*dxKm) * (*dxKm) + (*dyKm) * (*dyKm));
}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-07-16 00:47:08 +00:00

offsetKmFromCenter() converts longitude degrees to km using a constant kKmPerDeg, but longitude distance varies by cos(latitude). This will noticeably distort aircraft positions/distances (especially at the default ~48° lat) and can mis-rank “closest” aircraft.

offsetKmFromCenter() converts longitude degrees to km using a constant kKmPerDeg, but longitude distance varies by cos(latitude). This will noticeably distort aircraft positions/distances (especially at the default ~48° lat) and can mis-rank “closest” aircraft.
@ -0,0 +754,4 @@
strncpy(out->callsign, plane.callsign, sizeof(out->callsign) - 1);
strncpy(out->desc, plane.desc[0] != '\0' ? plane.desc : plane.type, sizeof(out->desc) - 1);
RouteClient::formatRoute(plane.callsign, out->route, sizeof(out->route));
strncpy(out->alt, plane.alt, sizeof(out->alt) - 1);
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-07-16 00:47:07 +00:00

buildDetailSnapshot() uses strncpy(..., sizeof(buf)-1) but never writes the trailing '\0'. If the source string length equals the max (e.g., 8-char callsign, 35-char desc), out->callsign/out->desc/out->alt may be unterminated and later passed to String(next.callsign)/String(next.desc), causing out-of-bounds reads.

buildDetailSnapshot() uses strncpy(..., sizeof(buf)-1) but never writes the trailing '\0'. If the source string length equals the max (e.g., 8-char callsign, 35-char desc), out->callsign/out->desc/out->alt may be unterminated and later passed to String(next.callsign)/String(next.desc), causing out-of-bounds reads.
@ -0,0 +809,4 @@
strncpy(m_slotCallsign[slot], next.callsign, sizeof(m_slotCallsign[slot]) - 1);
} else {
m_slotCallsign[slot][0] = '\0';
}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-07-16 00:47:08 +00:00

m_slotCallsign[slot] is populated with strncpy(..., sizeof-1) but not explicitly null-terminated. If next.callsign is at the max length, m_slotCallsign can become unterminated and later strncmp() calls may read past the buffer.

m_slotCallsign[slot] is populated with strncpy(..., sizeof-1) but not explicitly null-terminated. If next.callsign is at the max length, m_slotCallsign can become unterminated and later strncmp() calls may read past the buffer.
@ -0,0 +35,4 @@
out[0] = '\0';
if (outLen == 0 || in == nullptr) {
return;
}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-07-16 00:47:08 +00:00

normalizeCallsign() writes out[0] = '\0' before checking outLen. If outLen==0, this is an out-of-bounds write (even though current callers pass a non-zero size).

normalizeCallsign() writes out[0] = '\0' before checking outLen. If outLen==0, this is an out-of-bounds write (even though current callers pass a non-zero size).
ericthelin (Migrated from github.com) approved these changes 2026-07-16 00:49:13 +00:00
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin havedill/plane-radar-pr:havedill/plane-radar-pr
git switch havedill/plane-radar-pr

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch dev
git merge --no-ff havedill/plane-radar-pr
git switch havedill/plane-radar-pr
git rebase dev
git switch dev
git merge --ff-only havedill/plane-radar-pr
git switch havedill/plane-radar-pr
git rebase dev
git switch dev
git merge --no-ff havedill/plane-radar-pr
git switch dev
git merge --squash havedill/plane-radar-pr
git switch dev
git merge --ff-only havedill/plane-radar-pr
git switch dev
git merge havedill/plane-radar-pr
git push origin dev
Sign in to join this conversation.
No description provided.