From 7b1032bfc75aaa19cf745df463fc68a42176aa90 Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Thu, 15 Oct 2026 15:15:49 -0700 Subject: [PATCH] docs(cctv): document the Toronto pack and the shared camera cap Adds the Toronto settings to .env.example and a current-state section for the pack, restores an approximate camera count in the README, and corrects the claim that adding a pack never trims another region: with the shared 4,000-camera cap, the largest packs give way round-robin. Fixes two stale comments about the list's refresh and the ground-height sidecar. --- .env.example | 3 +++ README.md | 2 +- docs/CURRENT-STATE.md | 20 +++++++++++++++++++- server/providers/cctv/constants.js | 11 ++++++----- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/.env.example b/.env.example index 4e12a8eca..966a64ba0 100644 --- a/.env.example +++ b/.env.example @@ -226,6 +226,9 @@ AISSTREAM_API_KEY= # CCTV_NYC_ENABLED= # off by default; set 1 only if you hold a NYC DOT data-sharing agreement (tmcdot@dot.nyc.gov) for the camera feed # CCTV_NYC_MAX_SOURCES=250 # cap cameras loaded from the NYC TMC catalog (nearest borough cores first) # CCTV_NYC_CAMERAS_URL= # override the NYC TMC catalog URL +# CCTV_TORONTO_ENABLED=1 # set 0 to disable the City of Toronto RESCU cameras +# CCTV_TORONTO_MAX_SOURCES=336 # cap cameras loaded from Toronto RESCU (clamped to 8–500) +# CCTV_TORONTO_LIST_URL= # override the Toronto RESCU camera list URL # CCTV_MAX_SOURCES=4000 # catalog-wide ceiling, shared round-robin across packs # CCTV_PREFER_AUSTIN=1 # prioritize Austin cameras in the registry # CCTV_FORCE_AUSTIN= # force live default sources when a source-pack JSON is configured diff --git a/README.md b/README.md index 5fb666162..e78bcb404 100644 --- a/README.md +++ b/README.md @@ -377,7 +377,7 @@ Twenty layers and map sources. **Eighteen have a keyless path.** Some offer addi | 🌍 **Earthquakes** | Global seismic activity, last 24h | USGS | 🟢 | | ◍ **Air quality** | Live AQHI on the published 1–10+ health-risk scale, with a Weather-panel card showing the band legend and the highest readings in view. **Canada only** — ECCC is the first registered provider | ECCC MSC GeoMet | 🟢 | | 🚗 **Traffic** | Simulated vehicles on OSM roads. With TomTom, live flow speeds drive the simulation and congestion colors below ~8 km; individual vehicle positions are not live observations | TomTom + OSM | 🟢 simulation · 🟡 live flow speeds | -| 📹 **CCTV Mesh** | Public cameras projected _into_ the 3D space — Austin · Texas (TxDOT) · California (Caltrans) · London (TfL) · Ontario (511) · Finland (Fintraffic) · British Columbia (DriveBC) · Estonia (Tallinn, Tarktee) · Delaware (DelDOT live video) · New South Wales (Live Traffic NSW) · Calgary · Norway (Statens vegvesen) · Toronto, plus opt-in New York City (NYC DOT TMC, needs your own NYC DOT agreement). Positions are published; poses are estimated priors **you calibrate by dragging a gizmo on the camera itself** | City APIs | 🟢 | +| 📹 **CCTV Mesh** | ~4,000 public cameras (shared cap) projected _into_ the 3D space — Austin · Texas (TxDOT) · California (Caltrans) · London (TfL) · Ontario (511) · Finland (Fintraffic) · British Columbia (DriveBC) · Estonia (Tallinn, Tarktee) · Delaware (DelDOT live video) · New South Wales (Live Traffic NSW) · Calgary · Norway (Statens vegvesen) · Toronto, plus opt-in New York City (NYC DOT TMC, needs your own NYC DOT agreement). Positions are published; poses are estimated priors **you calibrate by dragging a gizmo on the camera itself** | City APIs | 🟢 | | 📷 **Mapped ALPR Cameras** | License-plate-reader camera locations tagged by OpenStreetMap contributors, loaded one city-sized view at a time, with **SHOW NEAREST**. Locations and tags only: no plate data, no video | OpenStreetMap (incl. DeFlock mapping) | 🟢 | | 📷 **Street Level** | Street-level photos behind one panel, one chip per provider: coverage on the streets, image cones, an embedded viewer and **FOLLOW**. Mapillary, Google Street View, KartaView and Panoramax | Mapillary · Google · KartaView · Panoramax | 🟢 KartaView, Panoramax · 🟡 Mapillary token · 🔴 Google Maps key | | 📻 **Radio** | Geolocated world radio with an **analog tuner** — drag the needle across up to 750 stations and the globe flies to each broadcaster | Radio Browser / broadcasters | 🟢 | diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index aab9d0447..0f5e3a05d 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -977,7 +977,25 @@ 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. +round-robin: no region is dropped outright, but when the packs together exceed +the ceiling, adding a pack trims cameras from the largest packs. + +## City of Toronto RESCU CCTV source pack + +The CCTV catalog adds the City of Toronto RESCU traffic cameras — downtown +arterials plus the Gardiner, DVP, Allen and Lake Shore, which the Ontario 511 +pack does not cover. The server reads the keyless camera list the City +publishes on its open data portal (`tmcearthcameras.json`, served as JSONP). +The list has no URL field: frame URLs are built from each validated, digits-only +camera number on the fixed origin +`https://opendata.toronto.ca/transportation/tmc/rescucameraimages/CameraImages/`. +The feed has no compass data, so headings are low-confidence priors. Some +cameras return a 200 "Image Unavailable" placeholder frame instead of an error. + +By default all ~336 cameras load, nearest downtown first. +`CCTV_TORONTO_MAX_SOURCES` sets the pack cap (8–500) and +`CCTV_TORONTO_ENABLED=0` turns the pack off. The pack shares the 4,000 +catalog-wide ceiling round-robin with the other packs. ## DriveBC CCTV source pack diff --git a/server/providers/cctv/constants.js b/server/providers/cctv/constants.js index e4837bdb4..b399088bb 100644 --- a/server/providers/cctv/constants.js +++ b/server/providers/cctv/constants.js @@ -309,7 +309,8 @@ export const DELDOT_ANCHORS = [ * City of Toronto RESCU traffic cameras: the municipal network the province's * 511 pack does not cover — downtown arterials plus the Gardiner, DVP, Allen * and Lake Shore. One keyless list for the whole city (~336 cameras), from the - * City's open data portal, refreshed within two minutes of any change. + * City's open data portal. It is fetched on every catalog refresh, but the + * upstream file is not updated often and may lag the live camera network. * * The list is served as JSONP (`jsonTMCEarthCamerasCallback({...})`); the * portal publishes the same data as .xml and .csv beside it. @@ -329,10 +330,10 @@ export const DEFAULT_TORONTO_MAX_SOURCES = 336; /** Yonge / Queen: the prioritization anchor. */ export const TORONTO_DOWNTOWN = { lat: 43.6532, lon: -79.3832 }; /** The city climbs from 76 m at the lake to 209 m at Steeles, so no single - * number fits: this is the mean across the 336 camera sites. Placement comes - * from the precomputed ground-height sidecar wherever a camera has an entry; - * this prior is only the fallback for a sidecar miss or an edited pose, and - * the client's ground snap corrects it wherever 3D tiles are loaded. */ + * number fits: this is the mean across the 336 camera sites. The ground-height + * sidecar has no Toronto entries yet, so this prior seeds placement; a camera + * that gains a sidecar entry uses it instead, and the client's ground snap + * corrects the prior wherever 3D tiles are loaded. */ export const TORONTO_GROUND_ELEVATION_M = 116; /** Hard ceiling on the RESCU list body. The whole city is ~336 rows and under * 60 KB; this only exists so an upstream that streams an unbounded body cannot