feat(cctv): seven camera packs, semantic labels, terrain-clear monitor planes (#433)

Seven contributed CCTV camera packs (Ontario 511, Fintraffic Finland, DriveBC, TxDOT Texas, Estonia Tallinn + Tarktee, Warendorf, Live Traffic NSW) on a fair per-pack catalog cap; semantic camera labels; monitor planes lifted clear of the terrain from a precomputed, bundled ground-height dataset. Default catalog 800 → 3,446 cameras. Full context in PR #433.

Co-authored-by: sendmebits <[email protected]>
Co-authored-by: avocadoAgent <[email protected]>
Co-authored-by: Alex Harvey <[email protected]>
Co-authored-by: Jason Meredith <[email protected]>
Co-authored-by: Daniel Smith <[email protected]>
Co-authored-by: Vladimir Sobolev <[email protected]>
Co-authored-by: Matthias Schneider <[email protected]>
Co-authored-by: Cyber Knight <[email protected]>
Co-authored-by: NovaSoft Australia <[email protected]>
This commit is contained in:
51 files changed
+78682 -939

No files matched your search

+15 -6
View File
@@ -8,9 +8,13 @@ import {
buildSyntheticCctvSvg,
proxyMediaResponse,
fetchCctvImageFromUpstream,
fetchTxdotSnapshot,
fetchCctvMediaUpstream,
} from './cctv/media.js';
import { CCTV_FRAME_FETCH_TIMEOUT_MS } from './cctv/constants.js';
import {
CCTV_FRAME_FETCH_TIMEOUT_MS,
CCTV_MAX_SOURCES_CEILING,
} from './cctv/constants.js';
import { googleServerApiKey } from './places/google-key.js';
export { CCTV_FRAME_FETCH_TIMEOUT_MS, fetchCctvImageFromUpstream };
/**
@@ -30,10 +34,10 @@ export function cctvProxy({ sourceRoot = process.cwd() } = {}) {
const getCctvSources = createCctvCatalog({ sourceRoot });
/** @type {Map<string,{id:string,status:string,sourceKind:string,label:string,message:string,updatedAt:number}>} */
const health = new Map();
/** Cap on health map entries to prevent unbounded growth. Sized to cover the
* full served catalog (CCTV_MAX_SOURCES hard-bounds at 1200) so health/status
* observability isn't silently evicted for a default 800-camera catalog. */
const HEALTH_MAX_ENTRIES = 1200;
/** Cap on health map entries to prevent unbounded growth. Sized to the
* CCTV_MAX_SOURCES ceiling so health/status observability is never evicted
* for any catalog the proxy can actually serve. */
const HEALTH_MAX_ENTRIES = CCTV_MAX_SOURCES_CEILING;
/** Update the health entry for a camera, evicting the oldest entry if at capacity. */
const setHealth = (cameraId, patch) => {
@@ -151,6 +155,9 @@ export function cctvProxy({ sourceRoot = process.cwd() } = {}) {
source.sourceKind || (source.url ? 'configured' : 'fallback'),
poseSource: source.poseSource,
license: source.license,
credit: source.credit || '',
code: source.code || '',
groundHeights: source.groundHeights || null,
})),
};
res.writeHead(200, {
@@ -328,7 +335,9 @@ export function cctvProxy({ sourceRoot = process.cwd() } = {}) {
: '');
const upstreamImage =
await fetchCctvImageFromUpstream(upstreamCandidate);
source?.sourceKind === 'txdot-its'
? await fetchTxdotSnapshot(upstreamCandidate)
: await fetchCctvImageFromUpstream(upstreamCandidate);
if (upstreamImage?.ok) {
setHealth(cameraId, {
status: 'ok',