mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 10:53:59 +00:00
Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts: # DATA_SOURCES.md # docs/CURRENT-STATE.md # server/providers/cctv/constants.js # server/providers/cctv/sources.js
This commit is contained in:
commit
6f054408da
71 files changed
+5228
-181
No files matched your search
+94
-7
@@ -914,6 +914,24 @@ owners. Tuner calculations have a pure entry, with existing layer exports
|
||||
preserved. Destruction removes listeners and state subscriptions before ending
|
||||
tuning; a delayed Enable result cannot reveal or refocus removed controls.
|
||||
|
||||
## NYC DOT TMC CCTV source pack
|
||||
|
||||
The CCTV catalog can add New York City traffic cameras from the NYC DOT
|
||||
Traffic Management Center. NYC DOT requires developers to sign a data-sharing
|
||||
agreement for the camera feed, so this is the one opt-in pack: it loads only
|
||||
when `CCTV_NYC_ENABLED=1`, and with the flag unset the server makes no NYC
|
||||
request. NYC DOT's requested disclaimer is in the Data attribution popover.
|
||||
When enabled, the server reads the keyless
|
||||
camera list at `https://webcams.nyctmc.org/api/cameras` and keeps cameras the
|
||||
feed marks online. Frame URLs are built from each camera UUID under
|
||||
`https://webcams.nyctmc.org/api/cameras/<uuid>/image`; they are never taken
|
||||
from the payload. There is no heading in the feed, so gizmos use the shared
|
||||
id-hash fallback at low confidence.
|
||||
|
||||
Once enabled, the 250 cameras nearest the five borough cores load.
|
||||
`CCTV_NYC_MAX_SOURCES` sets the pack cap (8–400). The catalog-wide ceiling stays at 4,000 and is shared
|
||||
round-robin, so adding this pack does not silently drop another region.
|
||||
|
||||
## DriveBC CCTV source pack
|
||||
|
||||
The CCTV catalog adds DriveBC highway cameras for British Columbia alongside the
|
||||
@@ -1092,6 +1110,19 @@ normal fallback chain. The existing declared media size ceiling remains 64 MiB.
|
||||
|
||||
## GBFS upstream bounds
|
||||
|
||||
Station information is normalized in `src/sources/gbfsStations.js` for both the
|
||||
globe layer and `get_bike_share`. Names accept legacy strings or GBFS v3 Localized
|
||||
String arrays regardless of the reported feed version. Nonempty English text
|
||||
(including regional `en-*` tags, case-insensitive) takes precedence, then the first
|
||||
usable translation. An unusable `name` falls back to `short_name` with the same
|
||||
rules; if neither supplies text, the station remains available with an empty name
|
||||
(the globe uses its station-ID label and the tool returns `null`). Malformed
|
||||
translation entries do not interrupt loading of the other stations. This covers
|
||||
station names, not complete GBFS v3 support.
|
||||
`scripts/qa-gbfs-names.mjs` checks synthetic localized names through the real layer,
|
||||
station selection, keyboard dismissal, mobile cards and bike-share tool against
|
||||
either a dev or preview server (`--url` selects the target).
|
||||
|
||||
The station reader addresses the proxy as `/api/gbfs/<encoded feed URL>`; the
|
||||
feed address is read from the path, and a query-string form is refused with a 400. GBFS refuses upstream redirects and enforces its 5 MiB response cap while
|
||||
streaming. The 12-second deadline includes reading the body, and rejected or
|
||||
@@ -1184,6 +1215,10 @@ The Node-only `gods-eye-view/server/providers/space` export supplies factories;
|
||||
`sources/space` supplies fixed upstream URL builders with no I/O or environment
|
||||
access. Callers retain validation, transport and response policy.
|
||||
|
||||
The shared TLE text parser skips incomplete named sets and resumes at the next
|
||||
complete set. A missing orbital line does not discard the later satellites in
|
||||
the catalog; satellite layers and next-pass tools use the same parser.
|
||||
|
||||
## Build configuration and local provider boundaries
|
||||
|
||||
`vite.config.js` delegates to `server/standalone/vite.config.js`, which loads
|
||||
@@ -3054,7 +3089,7 @@ its criteria cannot be silently ignored.
|
||||
| Satellites | CelesTrak | `src/data/satellites.js` | `/api/celestrak` | 120s |
|
||||
| Space Missions (30d) | Launch Library 2 + CelesTrak | `src/data/rocketLaunches.js` | `/api/launches` + `/api/celestrak/active` | 5 min |
|
||||
| Traffic | Selectable TomTom / OpenStreetMap / Hybrid roads; optional TomTom flow (BYOK) | `src/data/traffic.js` | browser-direct OpenFreeMap tiles; `/api/tomtom` for flow | viewport-driven; capped tile cache |
|
||||
| CCTV | Austin + Caltrans (CA) + TfL London + Ontario 511 + Fintraffic (FI) + DriveBC (BC) + TxDOT (TX) + Estonia (Tallinn, Tarktee) + Live Traffic NSW + Open Calgary Open Data + Statens vegvesen (NO, stills + live HLS, Kartverket ground heights) + Street View fallback | `src/data/cctv.js` | `/api/cctv` | 10s (active) |
|
||||
| CCTV | Austin + Caltrans (CA) + TfL London + Ontario 511 + Fintraffic (FI) + DriveBC (BC) + TxDOT (TX) + Estonia (Tallinn, Tarktee) + Live Traffic NSW + Open Calgary Open Data + Statens vegvesen (NO, stills + live HLS, Kartverket ground heights) + NYC DOT TMC (opt-in) + Street View fallback | `src/data/cctv.js` | `/api/cctv` | 10s (active) |
|
||||
| Radio | Radio Browser (public-domain station directory) | `src/data/radio.js` | `/api/radio/stations`, `/api/radio/click/:uuid` | 45 min directory refresh |
|
||||
| Transit 🚌 | Operator GTFS-Realtime VehiclePositions (7 keyless regions, `src/data/transitFeeds.js`) | `src/layers/transit/` via `src/app/layers/transit.js` | `/api/transit` | 15s (poll + delayed playback) |
|
||||
| Bikeshare 🚲 | GBFS (Lyft + BCycle) | `src/data/bikeshare.js` | `/api/gbfs` | 60s |
|
||||
@@ -3078,8 +3113,9 @@ shared 360°/flat and captured-since filters (relative days, so a link keeps its
|
||||
meaning), one viewer host and one on-globe credit per active provider. Each
|
||||
provider draws in one colour (`PROVIDER_COLORS` in
|
||||
`src/layers/streetLevel/policy.js`); 360° cones are rings and the selected
|
||||
sequence is GEV cyan. Share options: `m` (Mapillary), `p` (`a`/`p`/`f`
|
||||
panoramas), `s` (since, days). Only Mapillary is registered. Without
|
||||
sequence is GEV cyan. Share options: `m` (Mapillary), `r` (the other providers' switches by id,
|
||||
e.g. `google-1` for Street View), `p` (`a`/`p`/`f` panoramas), `s` (since, days). Mapillary and Google
|
||||
Street View are registered. Without
|
||||
`MAPILLARY_CLIENT_TOKEN` the panel reads KEY REQUIRED and the controls are
|
||||
disabled. With it, coverage draws as z0–5 overview points from orbit and z11–14
|
||||
sequence lines below 60 km; the proxy strips the unused `image` layer from z14
|
||||
@@ -3103,8 +3139,15 @@ miss cooldown. Roads on elevated decks are still drawn at
|
||||
ground level. Framing a photo ignores mesh samples far below the bare earth
|
||||
(unloaded tiles).
|
||||
|
||||
The header pill is the layer switch. With one provider its chip is a layer
|
||||
switch too; with several, darkening the last lit chip turns the layer off. The
|
||||
The header pill is the layer switch. Lighting a chip swaps the source;
|
||||
clicking the lit chip turns the layer off. A chip without a usable key
|
||||
explains the key instead of switching, and the other chips keep switching.
|
||||
Lit off its map stack, a provider leaves the panel saying which map it
|
||||
needs. When the switched-on providers lack
|
||||
their keys but a switched-off one would draw with a key already set (no
|
||||
Mapillary token, Street View on Google 3D with a Google key), the layer
|
||||
reports it (`keyAlternatives`), and the panel's KEY REQUIRED, its coverage
|
||||
line and the layer row's tooltip say to light it. The
|
||||
viewer sits under the header with EXPAND, FIT/FILL, FOLLOW and close above the
|
||||
image. FOLLOW needs the Google 3D map stack (`attachMapStackController`) and
|
||||
stops when the stack changes. Camera moves go through the application's
|
||||
@@ -3125,8 +3168,52 @@ manages each provider's credit and fans the filter out to every provider. To
|
||||
add a provider: implement the definition, register it in
|
||||
`src/app/layers/streetLevel.js`, add its boolean option to the `street-level`
|
||||
group in `src/data/layerState.js` and its modules to
|
||||
`scripts/package-boundaries.json`. Once a keyless provider registers, the
|
||||
layer's `requiresKeyId` becomes null and the key gate moves to the chips.
|
||||
`scripts/package-boundaries.json`. With providers on different keys the
|
||||
layer's `requiresKeyId` is null and each chip reports its own key.
|
||||
|
||||
Google Street View (`providers/google/`) runs on the Maps JavaScript API with
|
||||
the browser `GOOGLE_MAPS_API_KEY`, which needs that API enabled; it is loaded
|
||||
on first use (`mapsLoader.js`, CSP `script-src https://maps.googleapis.com`).
|
||||
Its chip starts off (`defaultOn: false`; a link without its switch keeps it off) because every
|
||||
panorama load is billed to the key. Google's terms forbid Street View beside
|
||||
non-Google maps, so the provider declares `requiresMapStack: 'photoreal'`:
|
||||
off Google 3D it does not appear at all (no chip, legend swatch, globe
|
||||
credit, layer source or button, and Google's script is not loaded), lookups
|
||||
and opens skip it, and leaving Google 3D closes its panorama; the share
|
||||
option keeps the user's choice for when Google 3D returns. Google offers no coverage layer
|
||||
for other maps, so it draws none: with it on, a click on the map itself
|
||||
(`scenePick.isSurfacePick`: nothing picked or Google 3D tile content, so a
|
||||
Mapillary line under the pointer wins; no tool holding the pointer; camera
|
||||
below 3 km) opens its nearest Google-collected outdoor panorama within 50 m
|
||||
and leaves the camera where it is (`groundClick.js`). Higher up the hint
|
||||
says to zoom in. **OPEN STREET VIEW** beside that hint (`#sl-nearest-btn`)
|
||||
does the same at the view centre, so Street View needs no pointer; it is
|
||||
disabled until the camera is at street zoom (and aimed at the sky, it opens
|
||||
nothing and says to aim at a street). One provider is lit at a time:
|
||||
`setProviderEnabled(id, true)` darkens the others, a chip click sends every
|
||||
switch in one update so the share link records the swap, and params that
|
||||
light several keep the one already on, else the first in chip order
|
||||
(`litByParams`; reapplying them never flips). Mapillary, free, is lit by
|
||||
default. The chip reads GOOGLE STREET VIEW, and an open panorama's globe
|
||||
marker is a Google-blue view cone (`marker: {kind: 'view-cone'}`) in place
|
||||
of GEV's amber pin. Its
|
||||
panoramas are all 360° and it draws no coverage, so it declares `filters: []`
|
||||
(a provider's `filters` default to both `pano` and `since`): lookups ignore
|
||||
the IMAGERY and SINCE filters, the panel hides each filter row no lit provider
|
||||
honours (`filterControls`), and the legend lists only providers that draw
|
||||
lines, with "Selected" only beside one of them. The viewer is Google's `StreetViewPanorama` in its own
|
||||
element in the viewer host, without Google's fullscreen, close and address
|
||||
controls (the address goes in the caption); a pose goes out at once and
|
||||
again when the panorama's month, photographer and address arrive (one
|
||||
successful lookup per panorama per session, seeded by the nearest lookup;
|
||||
a details lookup that fails or takes over ten seconds waits five seconds
|
||||
before a view event can retry, and an unmount drops lookups in flight). A key
|
||||
Google refuses (`gm_authFailure`: the API not enabled, a referrer it does
|
||||
not allow, billing off) reads KEY REJECTED and fails a pending open at
|
||||
once; a lookup or open Google never answers fails after 10 or 20 s. In CI
|
||||
(no Google key, no Google 3D) the gate checks that nothing of Street View
|
||||
shows off Google 3D, even switched on by a share link; the click and button
|
||||
step skips as `no Google key`.
|
||||
|
||||
Street Level has two browser gates. `npm run qa:street-level -- --url <server>`
|
||||
runs against real Mapillary and needs `MAPILLARY_CLIENT_TOKEN`. `npm run
|
||||
|
||||
Reference in new issue
Block a user