mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Merge remote-tracking branch 'upstream/main' into fix/363-geocode-proxy
# Conflicts: # CHANGELOG.md
This commit is contained in:
commit
5083a74413
542 files changed
+96845
-3034
No files matched your search
+16
-9
@@ -105,14 +105,17 @@ checks when changing this wiring.
|
||||
|
||||
`src/search` owns forward/reverse geocoding, place search and route provider
|
||||
interfaces. `createStandaloneApplication({ geospatial })` accepts `endpoints`
|
||||
and `providers`; the defaults preserve Google/Photon search, Google place context
|
||||
and the local OSRM route proxy. Location, annotations, HUD labels and voice use
|
||||
the composed service. Provider-specific credentials belong in the selected
|
||||
transport; server secrets never belong in browser configuration.
|
||||
and `providers`. Default forward search tries decimal coordinates and bundled
|
||||
place names (`presets`) first, without a network request, then Google when a key
|
||||
is configured, Photon, and the local `/api/geocode` Nominatim route. The
|
||||
defaults also keep Google place context and the local OSRM route proxy.
|
||||
Location, annotations, HUD labels and voice use the composed service.
|
||||
Provider-specific credentials belong in the selected transport; server secrets
|
||||
never belong in browser configuration.
|
||||
|
||||
For a compatible protocol, configure `geocode`, `photon`, `reverse`, `textSearch`,
|
||||
`nearby` or `route` endpoints. These are developer-selected configuration, not
|
||||
URLs accepted from page queries or model arguments. A different protocol supplies
|
||||
For a compatible protocol, configure `geocode`, `photon`, `nominatim`, `reverse`,
|
||||
`textSearch`, `nearby` or `route` endpoints. These are developer-selected
|
||||
configuration, not URLs accepted from page queries or model arguments. A different protocol supplies
|
||||
an adapter function instead. The exported `createDefaultPlaceSearch` constructor
|
||||
supports the same options for direct composition:
|
||||
|
||||
@@ -181,10 +184,14 @@ separate constructors. Pass these to `createApplication`; use its `signal` and
|
||||
`defer` for ownership. The compatibility catalog is still page-scoped: construct
|
||||
one application per page. Controls, actions and renderers use the same layer
|
||||
instances. Configure sources with `application/sources` before registration or
|
||||
state restoration, and release them after the consumers stop.
|
||||
state restoration, and release them after the consumers stop. The catalog
|
||||
constructor (`application/layers`) also requires `wind`, `weather` and
|
||||
`cyclones` sources with `getSnapshot` for the Weather layers, and owns the
|
||||
observed-history clock those layers share for the catalog's lifetime.
|
||||
|
||||
`application/services` accepts boundary, terrain, regional-context, weather and
|
||||
summary services. `application/requests` supplies the existing HTTP protocols
|
||||
summary services; its weather service supplies cockpit local conditions, not the
|
||||
Weather layers. `application/requests` supplies the existing HTTP protocols
|
||||
with configurable endpoints and a scoped transport. Changing an endpoint works
|
||||
only for a compatible protocol; another protocol supplies a service adapter.
|
||||
Cancellation discards late response bodies, and replacing a source invalidates
|
||||
|
||||
+91
-3
@@ -17,6 +17,8 @@ until deliberately adopted.
|
||||
Generated output, local configuration, browser evidence and bundled datasets are
|
||||
excluded. The formatter validates every entry before writing any file.
|
||||
|
||||
New world text labels must use the world-overlay host; Cesium text labels are forbidden.
|
||||
|
||||
## Current component ownership
|
||||
|
||||
Package imports use `gods-eye-view`; `package.json` is the authoritative
|
||||
@@ -277,6 +279,90 @@ share restoration and movement of controls between containers remain caller-owne
|
||||
Existing helper imports from `cockpitMath.js` and `rightRailPolicy.js` remain
|
||||
compatible through re-exports.
|
||||
|
||||
### Adding a right-rail readout panel
|
||||
|
||||
Add the shell in `src/ui/templates/context.html` inside `#right-context-rail`:
|
||||
a `.panel-collapsible` with a stable `id` and matching `data-panel-id`, the
|
||||
existing `.panel-header`, collapse button and a dedicated body. Register it
|
||||
with the existing panel chrome/layout owners; do not allocate rail space in
|
||||
the body renderer. Set `hidden` while empty so the allocator ignores it, and
|
||||
expand through the existing collapse button only on first appearance per page
|
||||
session, and only when the chrome marked the restored state as a default
|
||||
(`data-collapsed-preference`), never over a stored or shared choice. Preserve
|
||||
the user's later collapse choice, including body remounts. Mark the body
|
||||
`data-rail-scroller` when it scrolls: the rail's measuring pass lifts its
|
||||
`max-height` and puts the scroll offset back afterwards. Panel bodies only
|
||||
scroll on an open-card change, with one write, never on a refresh.
|
||||
|
||||
Compose `createRailCards({ container, document, onParams, onOpen })` and
|
||||
`createRailTimeline({ container, document, onCommit, onPreview, onStep,
|
||||
onLatest, onPlay })`. Cards reconcile `{ id, title, badge, open, compact,
|
||||
compactStatus, blocks }` in place. Their full-width native button headers expose
|
||||
`aria-expanded` and `aria-controls`; articles expose `data-open`. The feature
|
||||
adapter owns accordion state. Generic cards do not select data or enable layers.
|
||||
|
||||
`blocks` is an ordered array of loose, optional `{ id, type, ... }` descriptors,
|
||||
rendered by `railCardBlocks.js`. There are no per-section disclosures:
|
||||
|
||||
- `summary`: `text`, a single summary line.
|
||||
- `list`: `list: { ariaLabel, items }`, reconciled by `syncRowList` in `rowList.js`.
|
||||
- `lines`: keyed `lines: [{ id, text, muted? }]` for details and status.
|
||||
- `settings`: `settings: [{ id, label, chips }]`; each labelled row has a 56 px
|
||||
label column and a wrapping `syncChipGroup` from `chipGroup.js`.
|
||||
- `legend`: `legend: { colors, labels, units?, zeroIndex?, categorical? }` for a
|
||||
ramp/scale (including a physical freezing anchor) or separate keyed swatches.
|
||||
- `actions`: keyed `actions: [{ id, label, params?, href?, onClick?, disabled?,
|
||||
hint? }]` in a footer, using buttons or safe new-tab links.
|
||||
- `result`: `label`, keyed `lines`, and optional `clear: { params | onClick }`;
|
||||
its accessible × button sits beside the title.
|
||||
|
||||
Every block and control has a stable id. Lists, settings, actions and results
|
||||
can appear in any requested order, including a scene panel's rectangle action,
|
||||
results list, then selected-scene details. Chip/list/action `params` dispatch
|
||||
through `onParams(cardId, params)`; the feature adapter supplies
|
||||
`setLayerParams(id, params, { origin: 'user' })`. Current descriptors and disabled
|
||||
state are read at dispatch. Identical updates do not move nodes or write DOM;
|
||||
focused controls survive feed refreshes.
|
||||
|
||||
Weather descriptors retain top-level `chips`, `list` and `legend` for non-DOM
|
||||
consumers. They expose `summary.settings`, `summary.actions` and optional
|
||||
`summary.result`; wind also retains its raw captured `summary.reading`.
|
||||
`readout: true` layer rows render only the toggle and source/meta line; their
|
||||
subscriptions still refresh the cards. Cards own configuration and readings.
|
||||
|
||||
Weather orders cyclones, wind, then a bordered Observed history group containing
|
||||
the timeline and active radar, satellite and lightning cards. The group heading
|
||||
and scope name its active products. The timeline stays visible whenever any
|
||||
observed product is enabled; fewer than two ticks disables transport. Pass
|
||||
`heading: false` to the timeline when the containing group owns the heading.
|
||||
Exactly one active card is open. Header clicks and newly enabled ids choose it
|
||||
(the last new entry wins a batch); refreshes and clock ticks retain it. First
|
||||
appearance uses cyclones with storms, otherwise the first card. Disabling the
|
||||
open layer falls back to the first remaining card. A WeakMap per document keeps
|
||||
explicit choices through body remounts without adding share state. Card opening,
|
||||
storm selection and layer enabling remain independent.
|
||||
|
||||
Optional card/badge/slider class names provide feature styling. Card titles use
|
||||
`.data-name` typography; meta/time/badges use `.data-toggle-meta` typography;
|
||||
setting/result labels use `.panel-title`; chips retain `.data-toggle-chip`.
|
||||
Reserve one status line, even without a legend. Use app tokens. Wind's footer
|
||||
reads the map center into a result after the action. The captured location stays
|
||||
fixed until another read; model changes resample that location, units reformat
|
||||
it, and × clears both reading and map marker.
|
||||
|
||||
The timeline shows endpoint times and receives ticks, index, mode, playing,
|
||||
readout and disabled state. Its preview callback receives the tick and index and
|
||||
may return readout text; commits receive the same values after a 150 ms coalesced
|
||||
drag or final change. Feature adapters own data mapping and service subscriptions;
|
||||
generic modules own DOM/listeners/timers and release them in `destroy()`.
|
||||
|
||||
Keep persistence with panel chrome: collapse uses
|
||||
`godsEyeView.v6.panelCollapsed.<panelId>`, position uses
|
||||
`godsEyeView.v8.panelPos.<panelId>`, and share state uses the registered panel id.
|
||||
Do not rename existing
|
||||
ids or reset persistence versions when adding a body. The WEATHER adapter is
|
||||
`src/ui/weatherPanel.js`; its observed-history selection remains transient.
|
||||
|
||||
## Visual input
|
||||
|
||||
`gods-eye-view/ui/input` exports `bindApplicationShortcuts` and
|
||||
@@ -584,8 +670,8 @@ An empty search array is a definitive miss. HTTP failures, malformed results
|
||||
and oversized responses remain retryable. Attribution identifies OpenStreetMap /
|
||||
Nominatim.
|
||||
|
||||
Overpass currently supplies traffic road geometry, ALPR camera records, military
|
||||
installation footprints, and annotation geometry (administrative boundaries,
|
||||
Vector tile sources supply traffic roads, ALPR records and keyless military
|
||||
areas. Operator-configured Overpass supplies named installations and annotation geometry (administrative boundaries,
|
||||
neighborhoods, streets, building/grounds outlines and monument candidates).
|
||||
Nominatim forward/reverse lookup does not replace those queries. Layer source
|
||||
interfaces select traffic, camera and installation ingestion separately;
|
||||
@@ -627,7 +713,9 @@ query-language strings or decoding backend tags and relation members.
|
||||
|
||||
Points use `{lat, lon}`. Options carry `signal`. A successful array, including an
|
||||
empty array, is definitive; `null` means a transient failure;
|
||||
`{rateLimited: true, retryAfterMs}` retains a provider's retry delay. Candidates
|
||||
`{rateLimited: true, retryAfterMs}` retains a provider's retry delay.
|
||||
`{unavailable:true, code:'OVERPASS_NOT_CONFIGURED', retryable:false}` is a
|
||||
capability miss that stops retries while preserving pins and offline geometry. Candidates
|
||||
carry `id`, `names` (`primary`, `english`, `official`, `alternate`, `short`),
|
||||
`coordinates` (objects with `lat` and `lon`), `building` and optional `heightM`,
|
||||
`center` and `point`. Administrative candidates use `category: 'administrative'`
|
||||
|
||||
+987
-110
File diff suppressed because it is too large.
Load diff
@@ -36,7 +36,8 @@ const layers = createInfrastructureLayers({
|
||||
| `governorRequestRender` | `(reason)`; request a frame through the existing render scheduler |
|
||||
|
||||
Each returned layer supports `init(viewer)`, `enable(viewer)`, `disable(viewer)`,
|
||||
`update(viewer)`, `destroy(viewer)`, `getStats()` and `getLodDiagnostics()`.
|
||||
`update(viewer)`, `destroy(viewer)`, `getStats()`, `getLodDiagnostics()` and
|
||||
`getAnalystRecords()`.
|
||||
Use the same viewer for the instance's entire lifetime. Each viewer/context/overlay
|
||||
host permits one live instance per layer ID; destroy an old instance before
|
||||
replacing it. Separate applications may use identical IDs with separate hosts.
|
||||
|
||||
+62
-3
@@ -1,6 +1,6 @@
|
||||
# KNOWN ISSUES
|
||||
|
||||
Updated: July 8, 2026
|
||||
Updated: September 22, 2026
|
||||
|
||||
This file tracks active runtime issues only.
|
||||
|
||||
@@ -78,6 +78,56 @@ Status: Open (owner-accepted 2026-07-08, documented)
|
||||
|
||||
---
|
||||
|
||||
### Weather layers: coverage and meaning
|
||||
Status: Open (source limits, by design)
|
||||
|
||||
- **Rain radar covers the contiguous United States only.** It shows MRMS
|
||||
reflectivity in dBZ, not rainfall rate or a forecast; a gap in coverage does not
|
||||
mean no precipitation.
|
||||
- **Lightning density is a ground-network grid, not GLM flashes.** It is NOAA's
|
||||
15-minute density product derived from Vaisala NLDN/GLD360 on an approximately
|
||||
8 km grid, for the Americas and Pacific only (110°E across the dateline to 0°,
|
||||
25°S–80°N). It is not a live strike counter or an all-clear.
|
||||
- **Cyclone advisories cover NOAA's basins only:** the Atlantic and the
|
||||
eastern/central North Pacific (NHC and CPHC). Storms elsewhere do not appear.
|
||||
The cone is forecast-center uncertainty, not storm size.
|
||||
- **Satellite clouds:** global infrared is hourly with typically 2–3 hours of
|
||||
source latency. Clouds only is a brightness filter, not a cloud mask.
|
||||
- **Wind is a forecast.** The animation flows through one forecast on an
|
||||
approximately 1° grid and does not advance forecast time or follow the
|
||||
observed-history timeline.
|
||||
- **History is not shared.** Share links carry the weather layers and their
|
||||
settings but open at Latest.
|
||||
- **3D Tiles detail window during history playback:** when a frame's detail image
|
||||
is slow to arrive, the window may fall back to the coarser full-extent image
|
||||
until it does.
|
||||
- Native hardware GPU behavior of the wind and weather renderers is not yet
|
||||
verified.
|
||||
|
||||
---
|
||||
|
||||
### Satellite passes and analyst answers
|
||||
Status: Open (by design)
|
||||
|
||||
- Pass predictions search the next 24 hours for satellites in the loaded catalog.
|
||||
Visibility is a geometric estimate (satellite sunlit, observer's Sun at or
|
||||
below −6°); it ignores weather, satellite brightness and orbital-element age.
|
||||
- Analyst counts and ranks cover a bounded set of loaded records (by default
|
||||
2,000 per layer for satellites, datacenters and dams), so omitted records can
|
||||
change a nearest or count answer. Satellite distance is ground distance.
|
||||
|
||||
---
|
||||
|
||||
### Live camera video (HLS)
|
||||
Status: Open (limits)
|
||||
|
||||
- At most two live-video sessions run at once. RTMP-only sources and encrypted,
|
||||
fMP4 or byte-range playlists are not supported.
|
||||
- When live video fails, the camera falls back to its labeled still, Street View
|
||||
or placeholder frame, which is not live video.
|
||||
|
||||
---
|
||||
|
||||
## Closed / Intentional (for clarity)
|
||||
|
||||
### Proxy SSRF and error-surface hardening gaps
|
||||
@@ -118,5 +168,14 @@ Context:
|
||||
converted to **live NASA FIRMS data** on 2026-07-16: the `/api/firms` proxy merges
|
||||
three VIIRS NRT sources (trailing 24 h, 30 min cache, serve-stale-on-failure) and the
|
||||
bundled snapshot was deleted. Requires a free server-side `FIRMS_MAP_KEY`; without it
|
||||
the layer shows a KEY REQUIRED state.
|
||||
- Weather radar is still held out of OSS v1 after QA found the previous overlay did not provide reliable visible value.
|
||||
the layer row reads "Needs FIRMS_MAP_KEY — add it in Provider Settings".
|
||||
|
||||
---
|
||||
|
||||
### Weather radar held out of the open-source release
|
||||
Status: Closed — observed rain radar shipped (September 2026)
|
||||
|
||||
Context:
|
||||
- Rain radar, Satellite clouds, Lightning density, Wind and Cyclone advisories
|
||||
are in the Weather group of Data Layers. Their current limits are listed under
|
||||
"Weather layers: coverage and meaning" above.
|
||||
@@ -0,0 +1,82 @@
|
||||
# Local receivers
|
||||
|
||||
The Local ADS-B layer draws aircraft heard by your own receivers. It has two
|
||||
inputs, and it can use both at once.
|
||||
|
||||
| Input | What it is | Bands |
|
||||
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
|
||||
| Browser SDR | A USB RTL-SDR opened by the browser through WebUSB (Radio panel, Local RTL-SDR card). Decoding runs in the page. | 1090 MHz |
|
||||
| Decoder feed | The `aircraft.json` served by a decoder you run: dump1090-fa, readsb or tar1090 (1090 MHz), or dump978-fa + skyaware978 (978 MHz). | 1090 MHz, 978 MHz UAT |
|
||||
|
||||
Aircraft from both inputs are merged by ICAO address. The newest position
|
||||
wins, and the click card names every band and source that heard the aircraft
|
||||
in the last 60 s. Aircraft heard only on 978 MHz UAT draw with a thin ring.
|
||||
|
||||
Local aircraft usually lead their public twins. The public Flights layer
|
||||
renders positions about one poll interval (~30 s) behind so it can interpolate
|
||||
smoothly between fixes, while local receiver aircraft are shown as heard. An
|
||||
aircraft in both layers therefore draws twice, the magenta local marker ahead
|
||||
of the public one; both markers are drawn on purpose.
|
||||
|
||||
## Which to use
|
||||
|
||||
- **One plain RTL-SDR dongle, desktop Chrome or Edge:** use the browser SDR.
|
||||
Nothing else to install.
|
||||
- **A dual-band board, a Raspberry Pi feeder, or a dongle already used by a
|
||||
decoder:** use a decoder feed. A USB dongle can be opened by only one program
|
||||
at a time, so a dongle that dump1090 or dump978 owns cannot also be opened by
|
||||
the browser.
|
||||
|
||||
## Configuring feeds
|
||||
|
||||
Feeds are set in the server environment only (`.env`), never in the browser:
|
||||
|
||||
```sh
|
||||
LOCAL_RECEIVER_FEEDS=1090=http://localhost:8080/data/aircraft.json,978=http://localhost:8978/data/aircraft.json
|
||||
```
|
||||
|
||||
Each entry is `band=url`, where `band` is `1090` or `978`. The URL must:
|
||||
|
||||
- use `http` or `https`;
|
||||
- point at loopback, a private (RFC1918) address, `localhost` or a `*.local`
|
||||
name. Public addresses, link-local addresses (including `169.254.169.254`),
|
||||
IPv6 and other host names are refused;
|
||||
- have a path ending in `aircraft.json`, with no credentials, query or
|
||||
fragment.
|
||||
|
||||
An entry that breaks a rule is logged when the server starts, shown as
|
||||
`invalid` and never fetched. Restart the server after changing the value.
|
||||
|
||||
The server reads every feed about once a second while the Local ADS-B layer is
|
||||
on. A feed is `live`, `stale` (its own `now` is more than 10 s old, usually a
|
||||
stopped decoder), `unreachable` or `invalid`. The Layers panel row and the
|
||||
Local RTL-SDR card show these states.
|
||||
|
||||
## Example: dump1090-fa and dump978-fa on macOS or Linux
|
||||
|
||||
Write each decoder's JSON to a directory, then serve the directory on
|
||||
localhost. Each command keeps running, so start each in its own terminal:
|
||||
|
||||
```sh
|
||||
# 1090 MHz
|
||||
dump1090-fa --device-index 0 --write-json /tmp/adsb1090
|
||||
python3 -m http.server 8080 --bind 127.0.0.1 --directory /tmp/adsb1090
|
||||
|
||||
# 978 MHz UAT: dump978-fa decodes, skyaware978 writes aircraft.json
|
||||
dump978-fa --sdr driver=rtlsdr,rtl=1 --raw-port 30978
|
||||
skyaware978 --connect localhost:30978 --json-dir /tmp/adsb978
|
||||
python3 -m http.server 8978 --bind 127.0.0.1 --directory /tmp/adsb978
|
||||
```
|
||||
|
||||
```sh
|
||||
LOCAL_RECEIVER_FEEDS=1090=http://localhost:8080/aircraft.json,978=http://localhost:8978/aircraft.json
|
||||
```
|
||||
|
||||
A board with two identical-serial channels, such as the Nooelec FlyCatcher,
|
||||
cannot be told apart by serial number. Select each channel by index:
|
||||
`--device-index <n>` for dump1090-fa and `--sdr driver=rtlsdr,rtl=<n>` for
|
||||
dump978-fa. `rtl_test` lists the indexes.
|
||||
|
||||
A tar1090 or readsb install on a Raspberry Pi already serves
|
||||
`http://<pi-address>/tar1090/data/aircraft.json`. Use the Pi's private address
|
||||
or its `.local` name.
|
||||
Reference in new issue
Block a user