Skip to main content

The Detection Lifecycle

On the map, a camera glows to say it's currently detecting smoke or fire. That state has to turn on when detections start and — just as importantly — turn off when they stop, without a human closing anything. A detection isn't a moment; it's a window that opens on the first hit and closes automatically after the hits stop. This lesson is how that window is managed, because "is this camera detecting" is the piece of state operators trust most.

The one idea to hold on to​

The "detecting" state is an active CondorEventEntity, kept alive by fresh detections and closed automatically by a stale-event timer — with a change feed that reacts to the closure by clearing the camera's flags. Three moving parts, one window:

Keeping the window open​

Every detection (from the reconcile) does two things that keep the state alive:

  • Refreshes the incident — the active CondorEventEntity gets LastUpdatedDate = now and its TTL reset to 3 hours. As long as detections keep coming, the incident never goes stale.
  • Sets the camera flags — on the CameraOperational doc: HasAiDetectionHit (any detection) plus the type-specific HasRecent60DetectionHit, HasRecentPanoDetectionHit, or HasRecentVideoDetectionHit, and LatestAiDetectionStartDate / LatestAiDetectionDate. These flags are exactly what the frontend reads to render the "detecting" indicator.

So while a fire is being detected, each new hit slides the window forward — the camera stays lit.

Closing the window, automatically​

When detections stop, two functions cooperate to close the window — and the split between them is a clean example of separating a decision from its effect:

  • CleanupStaleDetectionFlags (timer, every 2 minutes) makes the decision. It finds active CondorEventEntitys whose LastUpdatedDate is older than 10 minutes and sets their status to Expired. Ten minutes of silence means the window is over.
  • CondorEventChangeFeed (a Cosmos change-feed trigger on the condorEvent container) applies the effect. It reacts only to events that have moved away from Active, and calls ResetCameraDetectionFlags — clearing HasAiDetectionHit and the type flags and nulling LatestAiDetectionStartDate. The camera stops glowing.

The timer decides when; the change feed reacts to the resulting status change to update the camera. Either the timer expires an event, or something else resolves it — either way the change feed is the single place the flags get cleared, so they can't be forgotten.

Gotcha: two clocks — the 10-minute window and the 3-hour TTL

There are two different timers on the incident and they do different jobs. The 10-minute staleness check is the one that drives the UX: it's what turns "detecting" off promptly after detections stop. The 3-hour TTL on the Cosmos doc is a backstop — Cosmos deletes the event document outright after that, so even if the timer or change feed failed, an incident can't live forever. Don't confuse them: raise the 10-minute value to keep cameras "detecting" longer; the TTL is just garbage collection.

Wrapping up​

A camera's "detecting" state is an active Cosmos CondorEventEntity that fresh detections keep alive (refreshing its LastUpdatedDate and 3-hour TTL, and setting the camera flags). A 2-minute timer expires events after 10 minutes of silence, and the condorEvent change feed reacts to that status change by clearing the camera's flags — so the window closes on its own. The 10-minute check drives the UX; the TTL is a backstop.

Detections light up the map and the console for operators. The other half of the app turns a confirmed threat into a message people act on. Next: From Alert to Reaction.