mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 19:04:02 +00:00
Merge remote-tracking branch 'upstream/main' into fix/houston-cctv-pack
# Conflicts: # .env.example # README.md # docs/CURRENT-STATE.md # server/providers/cctv/catalog.js # server/providers/cctv/normalize.js # server/providers/cctv/sources.js # src/data/dataCredits.js
This commit is contained in:
913 files changed
+81152
-21200
No files matched your search
@@ -18,7 +18,7 @@ export const CCTV_MAX_SOURCES_CEILING = 5000;
|
||||
export const AUSTIN_DOWNTOWN = { lat: 30.2672, lon: -97.7431 };
|
||||
/** Caltrans CCTV: one JSON feed per district, identical schema statewide. */
|
||||
/** TxDOT ITS: one keyless JSON catalog per district (25 districts statewide). */
|
||||
export const TXDOT_ORIGIN = 'https://its.txdot.gov';
|
||||
const TXDOT_ORIGIN = 'https://its.txdot.gov';
|
||||
export const TXDOT_CCTV_STATUS_URL = (district) =>
|
||||
`${TXDOT_ORIGIN}/its/DistrictIts/GetCctvStatusListByDistrict?districtCode=${encodeURIComponent(district)}`;
|
||||
/** Per-camera frame. Returns JSON `{snippet:<base64 jpeg>}`, not an image body;
|
||||
@@ -113,13 +113,34 @@ export const CALTRANS_ANCHORS = [
|
||||
{ lat: 32.7157, lon: -117.1611 }, // San Diego
|
||||
{ lat: 38.5816, lon: -121.4944 }, // Sacramento
|
||||
];
|
||||
export const FLORIDA_CCTV_URL =
|
||||
'https://services.arcgis.com/3wFbqsFPLeKqOlIK/arcgis/rest/services/FL511_Traffic_Cameras/FeatureServer/0/query';
|
||||
export const FLORIDA_IMAGE_HOSTS = [
|
||||
'images-dis.divas.cloud',
|
||||
'snapshots.divas.cloud',
|
||||
];
|
||||
export const DEFAULT_FLORIDA_MAX_SOURCES = 500;
|
||||
/** Byte cap per catalog page (2,000 rows, about 650 KiB measured). */
|
||||
export const FLORIDA_MAX_CATALOG_BYTES = 2 * 1024 * 1024;
|
||||
/** Catalog page ceiling: 40 pages covers 4,000+ cameras even at 100 rows a page. */
|
||||
export const FLORIDA_MAX_CATALOG_PAGES = 40;
|
||||
export const FLORIDA_ANCHORS = [
|
||||
{ lat: 25.7617, lon: -80.1918 }, // Miami
|
||||
{ lat: 28.5384, lon: -81.3789 }, // Orlando
|
||||
{ lat: 27.9506, lon: -82.4572 }, // Tampa
|
||||
{ lat: 30.3322, lon: -81.6557 }, // Jacksonville
|
||||
{ lat: 30.4383, lon: -84.2807 }, // Tallahassee
|
||||
{ lat: 26.1224, lon: -80.1373 }, // Fort Lauderdale
|
||||
{ lat: 26.7153, lon: -80.0534 }, // West Palm Beach
|
||||
{ lat: 30.4213, lon: -87.2169 }, // Pensacola (panhandle)
|
||||
];
|
||||
/** TfL JamCams: one keyless list endpoint; frames live on a public S3 bucket. */
|
||||
export const TFL_JAMCAM_URL = 'https://api.tfl.gov.uk/Place/Type/JamCam';
|
||||
export const TFL_IMAGE_ORIGIN =
|
||||
'https://s3-eu-west-1.amazonaws.com/jamcams.tfl.gov.uk/';
|
||||
export const DEFAULT_TFL_MAX_SOURCES = 250;
|
||||
export const LONDON_CENTER = { lat: 51.5074, lon: -0.1278 };
|
||||
/** Ontario 511: keyless CARS/511 camera catalog; frame URLs are still images. */
|
||||
/** Ontario 511: CARS/511 camera catalog, which needs a developer key (ONTARIO_511_API_KEY); frame URLs are still images. */
|
||||
export const ONTARIO_511_CAMERAS_URL =
|
||||
'https://511on.ca/api/v2/get/cameras?format=json&lang=en';
|
||||
export const ONTARIO_511_IMAGE_ORIGIN = 'https://511on.ca/map/Cctv/';
|
||||
@@ -188,6 +209,8 @@ export const TARKTEE_IMAGES_URL =
|
||||
'https://tarktee.transpordiamet.ee/api/v1/datex/roadCameraImages';
|
||||
export const TARKTEE_IMAGE_ORIGIN = 'https://tarktee.transpordiamet.ee/images/';
|
||||
export const DEFAULT_TARKTEE_MAX_SOURCES = 179;
|
||||
/** Hard ceiling per Tarktee DATEX XML document (~120–165 KB live). */
|
||||
export const TARKTEE_MAX_CATALOG_BYTES = 4 * 1024 * 1024;
|
||||
export const TARKTEE_ANCHORS = [
|
||||
{ lat: 59.437, lon: 24.753 }, // Tallinn
|
||||
{ lat: 58.378, lon: 26.729 }, // Tartu
|
||||
@@ -286,6 +309,36 @@ export const CATALONIA_ANCHORS = [
|
||||
{ lat: 41.5636, lon: 2.0111 }, // Terrassa
|
||||
];
|
||||
|
||||
/** Hong Kong Transport Department traffic snapshot cameras: keyless English
|
||||
* locations XML on DATA.GOV.HK; frames are stills on the TD CCTV host. */
|
||||
export const DEFAULT_HK_CAMERAS_URL =
|
||||
'https://static.data.gov.hk/td/traffic-snapshot-images/code/Traffic_Camera_Locations_En.xml';
|
||||
/** The only origin HK camera frames may come from. Verified 2026-10-11: still
|
||||
* URLs answer 200 on this host with no redirect hop. */
|
||||
export const HK_IMAGE_ORIGIN = 'https://tdcctv.data.one.gov.hk/';
|
||||
/** Above the full TD English catalog (~1,013 cameras) so a default install
|
||||
* keeps nearly all of them. Catalog-wide round-robin still applies when the
|
||||
* sum of packs exceeds DEFAULT_CCTV_MAX_SOURCES (Norway-style). */
|
||||
export const DEFAULT_HK_MAX_SOURCES = 1100;
|
||||
/** Prioritization anchors across Hong Kong Island, Kowloon and the New
|
||||
* Territories so a lowered cap keeps territory-wide coverage rather than
|
||||
* only the harbour corridor. */
|
||||
export const HK_ANCHORS = [
|
||||
{ lat: 22.2819, lon: 114.158 }, // Central
|
||||
{ lat: 22.2976, lon: 114.1722 }, // Tsim Sha Tsui
|
||||
{ lat: 22.3827, lon: 114.19 }, // Sha Tin
|
||||
{ lat: 22.3701, lon: 114.114 }, // Tsuen Wan
|
||||
{ lat: 22.4503, lon: 114.1688 }, // Tai Po
|
||||
{ lat: 22.493, lon: 114.139 }, // Fanling
|
||||
{ lat: 22.391, lon: 113.977 }, // Tuen Mun
|
||||
{ lat: 22.4445, lon: 114.022 }, // Yuen Long
|
||||
{ lat: 22.307, lon: 114.26 }, // Tseung Kwan O
|
||||
];
|
||||
/** Hard ceiling on the locations XML body. The live English list is ~400 KB
|
||||
* for ~1,000 cameras; this only exists so an unbounded upstream cannot be
|
||||
* buffered without limit. */
|
||||
export const HK_MAX_CATALOG_BYTES = 4 * 1024 * 1024;
|
||||
|
||||
/** Statens vegvesen (Norway) road cameras: the keyless OGC API Features view
|
||||
* of the official DATEX 3.1 CCTV site table, one GeoJSON request for the whole
|
||||
* country (~900 cameras). The raw DATEX node needs an account; this view does
|
||||
@@ -317,6 +370,49 @@ export const NORWAY_ANCHORS = [
|
||||
{ lat: 69.6492, lon: 18.9553 }, // Tromsø
|
||||
];
|
||||
|
||||
/** Kartverket's keyless point-height API (CC BY 4.0): terrain height above
|
||||
* sea level (NN2000), used as the Vegvesen cameras' ground prior because the
|
||||
* camera feed's points are 2D. */
|
||||
export const KARTVERKET_HEIGHT_URL =
|
||||
'https://ws.geonorge.no/hoydedata/v1/punkt';
|
||||
/** Points per request. The API takes up to 50, but above ~20 it answers the
|
||||
* extra points from contour lines (`hoydekurver`, metres to ~20 m off) or not
|
||||
* at all; at 20 nearly every camera resolves from the 1 m terrain model. */
|
||||
export const KARTVERKET_MAX_POINTS = 20;
|
||||
/** Requests in flight at once. The whole country is ~36 requests of
|
||||
* 0.6-9.5 s each, so a cold lookup takes ~6-13 s. */
|
||||
export const KARTVERKET_CONCURRENCY = 8;
|
||||
/** Deadline for one complete lookup, shared by every request. A lookup cut
|
||||
* short by it is resumed on the next refresh, without a backoff. */
|
||||
export const KARTVERKET_LOOKUP_TIMEOUT_MS = 30 * 1000;
|
||||
/** One request that takes longer than this counts as a failing service. */
|
||||
export const KARTVERKET_REQUEST_TIMEOUT_MS = 10 * 1000;
|
||||
/** The Vegvesen lane's budget, measured from the start of the loader (catalog
|
||||
* fetch included), for waiting on heights. Under the 15 s per-provider fetch
|
||||
* timeout so this pack is never the catalog's slowest lane. A lookup still
|
||||
* running after it keeps filling the cache for the next refresh. */
|
||||
export const KARTVERKET_CATALOG_WAIT_MS = 12 * 1000;
|
||||
/** The lane only waits when more than this share of its cameras has no
|
||||
* answer yet (a cold cache). A few new cameras or expired misses are looked
|
||||
* up in the background instead of holding the refresh. */
|
||||
export const KARTVERKET_WAIT_MISSING_SHARE = 0.1;
|
||||
/** A point Kartverket has no height for (some ferry quays and bridges) is not
|
||||
* asked about again for this long. */
|
||||
export const KARTVERKET_NULL_TTL_MS = 6 * 60 * 60 * 1000;
|
||||
/** After a failing request (408, 429, 5xx, a network error, a request
|
||||
* timeout or an unreadable body), no lookup starts for this long, or for the
|
||||
* Retry-After the service sent, bounded to [1 min, 1 h]. Longer than the
|
||||
* 15-minute catalog refresh (CCTV_SOURCE_CACHE_MS), so a failing service
|
||||
* costs one attempt per backoff, not one per refresh. */
|
||||
export const KARTVERKET_FAILURE_BACKOFF_MS = 30 * 60 * 1000;
|
||||
export const KARTVERKET_MAX_BACKOFF_MS = 60 * 60 * 1000;
|
||||
export const KARTVERKET_MAX_RESPONSE_BYTES = 256 * 1024;
|
||||
/** Plausible Norwegian terrain: below sea level only at the shore, and no road
|
||||
* camera sits above ~1,500 m. Anything outside is treated as no height. */
|
||||
export const KARTVERKET_HEIGHT_RANGE_M = Object.freeze({ min: -20, max: 2500 });
|
||||
/** Same identity the other CCTV upstream requests send. */
|
||||
export const KARTVERKET_USER_AGENT = 'gods-eye-view-cctv-proxy/1.0';
|
||||
|
||||
/** NYC DOT Traffic Management Center cameras: one keyless JSON list for the
|
||||
* five boroughs (~980 cameras). Frames are stills synthesized from each
|
||||
* camera UUID on the city's webcam host — never taken from the payload. */
|
||||
@@ -470,6 +566,10 @@ export const CCTV_SOURCE_CACHE_MS = 15 * 60 * 1000;
|
||||
* pending forever — a hung fetch aborts, the loader returns [], and
|
||||
* serve-stale/other packs take over. */
|
||||
export const CCTV_SOURCE_FETCH_TIMEOUT_MS = 15 * 1000;
|
||||
/** Tarktee's two DATEX feeds (120 and 160 KB) answered in 2 to 16.6 s across
|
||||
* ten requests on 2026-10-18, so the shared 15 s timeout dropped the Estonian
|
||||
* pack on about a third of loads. Both must arrive for any camera to load. */
|
||||
export const TARKTEE_FETCH_TIMEOUT_MS = 30 * 1000;
|
||||
/** Individual CCTV image fetches must settle before the active 10-second
|
||||
* client refresh cadence. A bounded miss can fall through to Street View or
|
||||
* the synthetic frame instead of leaving the browser preview pending. */
|
||||
|
||||
Reference in new issue
Block a user