Keeps main's 4,000 catalog-wide camera cap, which main pins in tests; WSDOT
shares it round-robin with the other packs. The branch's earlier cap raise and
its removal of main's cap tests are reverted in this merge.
Register the keyless webcams.nyctmc.org catalog as a live CCTV source,
synthesize frame URLs from validated camera UUIDs, and keep the nearest
cameras to the five borough cores under the existing catalog ceiling.
Resolve the source-pack conflicts with Statens vegvesen (keep both packs).
The Norway pack's 900 default pushed the per-pack defaults to 5,204, past
the 4,500 catalog cap this PR enforces, so raise DEFAULT_CCTV_MAX_SOURCES
to 5,500 and CCTV_MAX_SOURCES_CEILING to 6,000.
- Lower the Vegvesen default cap to 900, still above the ~850 working
cameras, so the per-pack defaults stay closer to the catalog default.
- Name the flat ground-elevation prior as a known limitation: the feed
is 2D, and mountain-pass cameras can sit below terrain where neither
the point-height prior nor the ground snap resolves.
- README: ~3,900 public cameras.
- Use one HLS figure (~135 working) in CHANGELOG and DATA_SOURCES.
- DATA_SOURCES: list the frame and HLS hosts alongside the catalog host.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Norway's ~850 working road cameras load from one keyless GeoJSON request
to the agency's OGC API view of its DATEX 3.1 CCTV table, so no DATEX
account is needed. Faulty cameras are dropped, every camera sits under a
"Norway" category, and the ~135 that publish HLS play as live video
through the existing in-memory relay with the still as fallback. Frames
and manifests are pinned to each camera's own path on the agency hosts.
CCTV_VEGVESEN_ENABLED=0 disables the pack, CCTV_VEGVESEN_MAX_SOURCES
caps it (nearest the largest cities first) and CCTV_VEGVESEN_VIDEO=0
keeps stills only. Attributed under NLOD 2.0.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The per-pack defaults already summed to 4,054 before WSDOT (4,304 with
it), past the documented 4,000 cap, so a default install was trimming.
The existing sum check in the DriveBC test listed packs by hand and
missed Calgary and DelDOT. Replace it with a check in
cctvCatalogCap.test.mjs that sums every exported DEFAULT_*_MAX_SOURCES,
and drop the Calgary test that pinned the cap at exactly 4,000.
Adds Washington State's highway cameras as a keyless source pack, from the
Esri JSON layer WSDOT's own Travel Center map consumes
(data.wsdot.wa.gov/travelcenter/Cameras.json, ~1,700 point features).
Closes#624.
- Geometry arrives in EPSG:3857; converted to WGS84 on load and bounded to
a Washington bounding box.
- Only frames on WSDOT's own images.wsdot.wa.gov host are registered — the
catalog also lists ~70 partner cameras (Oregon DOT, City of Seattle,
lodges, airports) whose own terms apply; those are skipped rather than
proxied. 1,630 cameras survive the filters against the live feed.
- CompassDirection letters (N/E/S/W) give a high-confidence heading; the
majority `B` ("both directions") rows carry no single facing and use the
shared id-hash fallback at low confidence, with the usual two pose
personalities.
- The feed body carries Windows-1252 bytes (en-dashes in titles) with no
charset declaration, so it is decoded explicitly before parsing.
- WSDOT's layer metadata marks the feed "low volume": the 15-minute catalog
cache and per-request frame fetches respect that, frames are never stored
or redistributed, and the WSDOT credit is registered in the attribution
popover. A keyed WSDOT Traveler Information API serves the same population
for higher-volume use and is deliberately not required.
- Defaults: 250 cameras nearest Seattle and Spokane; CCTV_WSDOT_MAX_SOURCES
changes the cap, CCTV_WSDOT_ENABLED=0 turns the pack off.
- Tests: Mercator conversion against a real layer feature, official-host and
malformed-row filtering, compass mapping and both pose personalities,
cp1252 decoding, env cap, upstream-failure fallback.
Wind (NOAA GFS and ECMWF IFS: animated particles, colour field, a reading at map centre), observed weather (NOAA MRMS radar, GOES and NESDIS infrared clouds, lightning density) on one shared history timeline, NHC and CPHC cyclone advisories with tracks and cones, and a WEATHER panel in the right rail. On 3D Tiles the observed products render as raised shells with a sharper window around the view.
Co-authored-by: Gustavo Beneduzi <[email protected]>
Co-authored-by: Daniel Slay <[email protected]>
Co-authored-by: Rehaan Delmotra <[email protected]>
Co-authored-by: Cursor Agent <[email protected]>
The media relay only deadlined the wait for upstream response headers. Once
headers arrived the timer stopped, so an upstream that answered and then sent
nothing held both the client response and the upstream socket open for as long
as the camera host allowed. The declared Content-Length ceiling was the only
body bound, and a chunked or length-less body had none.
A 30-second idle deadline now measures the gap between upstream chunks and
tears the stream down through the existing release path. Because a paused pipe
also stops upstream bytes arriving, the deadline reschedules itself whenever
the response is still waiting to drain, so a viewer on a slow link is not read
as a dead camera. Live feeds that keep delivering frames are unaffected.
Supersedes #438 by @rileygramlich, ported onto the current component layout with fixes from review.
Verified before merge: format, package boundaries, unit suite, build, and the browser tracking suite; a browser harness for the change where one applies; adversarial review applied.
Co-authored-by: rileygramlich <[email protected]>