From Detection to Event
A detection has arrived — through the poll, the event hub, or the video blob trigger.
Now the real work: turning a raw Condor payload into something the platform can use — a
durable record, a live map dot, a camera that lights up "detecting" in the operator's console.
That transformation is one method, ProcessCameraEvent, and it is the single most important
piece of this app to understand, because it's where a detection becomes an event.
The one idea to hold on to
One detection fans out across four data stores and reaches users two ways — and every ingestion path converges on this same reconcile. It isn't a "save"; it's a coordinated write to Cosmos, SQL, ESRI, and SignalR, in a fixed order. Walk it:
From the poll queue, the event hub, or the video blob trigger — all three converge on the same reconcile.
The reconcile, store by store
Here is what ProcessCameraEvent does with a detection, and exactly which data store each step
touches:
- Resolve the camera — Cosmos. Look up the camera in
CameraConfigby device id or by a matching stream id (Condor may report either). Then gate onCameraStatic: the camera must belong to this environment and be public — Condor feeds one API/hub for every environment, so each deployment must filter to its own cameras or it would process the whole fleet. Finally load theCameraOperationaldoc, which the flags below live on. - Open or refresh the incident — Cosmos. A camera that's actively detecting has one
CondorEventEntity(statusActive) — the incident that groups a burst of detections. If one exists it's refreshed; if not, one is created. Its 3-hour TTL andLastUpdatedDateare what the lifecycle uses to decide the detection window is still open. - Record the detection — SQL. Upsert a
CondorCameraEventrow, keyed on the Condor event id so a re-reported detection updates in place rather than duplicating. This is the durable, queryable record behind the per-camera AI detection log. - Enrich and store the detail — SQL. If the payload carries COCO detections, fetch fire localization (lat/lon, bearing, distance) from the Condor client — with a 10-minute freshness cutoff, so stale detections aren't geolocated — then bulk-insert the COCO detections and annotations through table-valued parameters (the tables from the Infrastructure Condor AI data docs).
- Feed the map — ESRI. Publish the fire localizations to ESRI Velocity — but only in poll mode. In event-hub mode ESRI subscribes to the same hub through its own consumer group, so this app stays silent to avoid double-publishing (the nuance from the ingestion lesson).
- Flip the camera flags — Cosmos. Patch the
CameraOperationaldoc: setHasAiDetectionHitplus the type-specific flag (HasRecent60DetectionHit,…Pano…, or…Video…). This is the "this camera is detecting right now" state. - Notify the frontend — SignalR. Broadcast the event to the camera's SignalR group. Every operator watching that camera sees the detection appear in real time.
The two ways a detection reaches a user
Steps 5 and 7 are the payoff — a detection becomes visible through two independent channels, and it helps to keep them distinct:
- The map (ESRI Velocity). Fire localizations become dots and vectors on the ArcGIS map, so the whole area's situation is visible at a glance — and, in event-hub mode, ESRI gets these straight from the hub, not from this app.
- The app (SignalR). The live per-camera broadcast plus the flipped operational flags mean the camera console and camera list update instantly — a camera glows "detecting," its latest detection shows, without a refresh.
It's easy to conflate the two Condor records, and they serve different jobs. The SQL
CondorCameraEvent is the permanent, queryable history — every detection ever, for logs and
analysis. The Cosmos CondorEventEntity is the ephemeral incident — TTL'd, refreshed by
each new detection, and expired when they stop (next lesson). A detection writes to both, but you
read the SQL row for history and the Cosmos incident for "is this camera detecting now."
Wrapping up
ProcessCameraEvent is the reconcile every ingestion path funnels into: it resolves and
environment-gates the camera (Cosmos), opens or refreshes the incident (Cosmos), records the
detection and its enriched COCO detail (SQL), feeds the map in poll mode (ESRI), flips the
camera's detection flags (Cosmos), and broadcasts to the frontend (SignalR). One detection, four
stores, two user-facing channels. The SQL row is history; the Cosmos incident is the live window.
That live window doesn't stay open forever. Next, how a detection turns "detecting" on and off: The Detection Lifecycle.