Tunas Akara
Back to Blog

SNMP for CCTV Fleets: Monitoring Cameras Before Footage Goes Missing

by RayhanUpdated 8 min read
cctvsnmpmonitoringiotvideo-analytics
SNMP for CCTV Fleets: Monitoring Cameras Before Footage Goes Missing

SNMP for CCTV Fleets: Monitoring Cameras Before Footage Goes Missing

A camera dead for six hours, discovered only when the footage is actually needed: that's the worst failure mode in a video analytics deployment. Not a bad model. Not a missed detection.

The analytics pipeline was fine. The dashboard looked fine. Nobody was watching the one signal that would have caught it: whether the device itself was still there.

I monitor camera fleets with SNMP for exactly this reason. It's an old, unglamorous protocol, and that's the point: every managed switch, PoE injector, NVR, and IP camera already speaks it. That makes it one channel I don't have to negotiate per vendor.

SNMP is the boring layer, and that's why it works

SNMP (Simple Network Management Protocol) is a request/response protocol for asking a device about itself: is it up, how long has it been up. It also asks what's happening on its network interfaces.

Every value lives at an OID (object identifier), a dotted address into the device's MIB, its catalog of available data. Three OIDs cover most of what a camera fleet needs day to day:

  • 1.3.6.1.2.1.1.3.0sysUpTime, time since the device last reinitialized, in hundredths of a second. A camera whose uptime just reset to zero rebooted, whether or not anyone told you.
  • 1.3.6.1.2.1.1.1.0sysDescr, the vendor's self-reported hardware and firmware string, useful for confirming what you're actually polling.
  • 1.3.6.1.2.1.2.2.1.8ifOperStatus per interface, whether a link is administratively and operationally up. On a PoE switch this tells you which downstream port just dropped, often before the camera itself stops answering.

None of this requires vendor-specific tooling. It's the same MIB-2 subtree on a $40 camera and a $4,000 switch.

Polling from a Node backend

For the Node backends I build for these deployments, I reach for net-snmp. It's a JavaScript implementation of SNMP v1, v2c, and v3, published under the MIT license. It gives you a session object with get(), getBulk(), walk(), and subtree(). There's also trap and inform support, if a device is capable of pushing alerts instead of waiting to be polled.

A minimal health poll looks like this:

const snmp = require("net-snmp");

const session = snmp.createSession(camera.ip, "public", { version: snmp.Version2c });

session.get(["1.3.6.1.2.1.1.3.0"], (error, varbinds) => {
  if (error) {
    markUnreachable(camera.id);
  } else {
    recordUptime(camera.id, varbinds[0].value);
  }
  session.close();
});

Run that against every device on the camera VLAN every 60 seconds. That gives you a reachability and uptime baseline for the whole fleet, switches included. No vendor SDK gets touched. getBulk() pulls the interface table in one round trip when walking counters across a switch with dozens of ports. It starts to matter once per-OID polling takes longer than the polling interval itself.

What SNMP can't see

This is the part that trips people up: a camera can answer SNMP correctly, uptime climbing, interface up, ping healthy. Meanwhile the actual video feed is frozen. Picture a car with the engine running and the speedometer moving normally, but the dashcam died a while ago. The dashboard says everything's fine; only the engine actually is.

The chip that runs the network stack and the pipeline that encodes frames are different subsystems on cheap camera hardware. A fault in the encoder or sensor doesn't necessarily take the network stack down with it. I've seen a camera hold a healthy SNMP session for hours after its RTSP stream had already stopped producing new frames.

Checking RTSP health properly means going past "did the connection open." A plain OPTIONS request against an RTSP URL is unreliable for this. Some cameras respond fine while otherwise stuck. Some error on streams that are actually healthy.

What works is a frame-age watchdog: open the stream, and track the timestamp of the last frame actually decoded. Alert once that age crosses a threshold. That threshold is usually 30 to 60 seconds, enough margin to avoid flooding on ordinary bitrate hiccups. ffprobe run periodically against each stream URL gives you that timestamp. So does a small consumer process using an RTSP/FFmpeg binding, without recording or displaying the video.

SNMP and the RTSP watchdog are answering two different questions, and a fleet dashboard needs both:

Loading diagram…

Device-down and stream-stale are different failure classes. One is usually a network or power problem. The other is usually a sensor, encoder, or storage-card fault, on a device that's still fully reachable on the network. Collapsing both into one status light loses the information that tells you which one you're dealing with.

Alerting: the same outage, two very different costs

A camera going dark for five minutes at 3 AM on a quiet loading dock is noise most nights. A PoE port blipped, the switch rebooted, it's back.

The same five-minute gap on the one camera covering an entrance is a different story. Discovered three days later while pulling footage for an incident review, that's the failure that actually costs something.

SNMP polling alone can't tell these apart; it just reports "was reachable" or "wasn't." The alert design has to carry that judgment instead:

  • Debounce transient flaps. Require the failure to hold across two or three poll cycles before paging anyone, or every switch reboot becomes a 3 AM alert.
  • Weight cameras by what they cover, not by device count. A parking-lot camera with a five-minute gap is a log line; an entrance or cash-point camera with the same gap is a page.
  • Track downtime duration per camera, not just current state. That way a camera flapping every twenty minutes shows up in a weekly report, even though it's "up" at any given check.

Fleet dashboard basics

The dashboard itself doesn't need to be elaborate. A table of camera, last SNMP response, uptime, last good frame timestamp, and current alert state covers the operational question: what's down right now. That's true for a fleet of any size I've worked with.

Both signals write into the same status store and read back as one row per device. Wiring that kind of ingestion into a live dashboard follows the same pattern covered in the guide to IoT backends. What catches incidents isn't a fancier UI. It's making sure both signals are collected before the day someone needs to answer "was this camera even working."

None of this replaces getting the camera itself hardened and configured correctly in the first place. See the firmware hardening checklist for what has to happen before a camera goes live. Monitoring tells you when a correctly configured device has stopped behaving like one. A camera that was never configured right will fail in ways no amount of polling catches.

The takeaway

A dead camera is cheap to detect and expensive to discover late. SNMP gives you reachability and uptime for free, across every device on the network, using a protocol every vendor already implements.

It won't tell you the stream froze; that needs a frame-age check against the actual RTSP feed. Run both, alert on them separately. The failure that used to surface during an incident review shows up instead on a dashboard, within a minute of happening.

Related Posts

Building something similar?

IoT Backend & Multi-Protocol Integration

Backends that ingest device telemetry across MQTT, WebSocket, Modbus, and BLE, and normalize it into reliable real-time dashboards.

See how I can help