Skip to main content

EverNVR

Connects GEM to an EverNVR recorder over its HTTPS API. The driver reads the camera list, creates a camera zone per camera, plays live video, fetches live and recorded snapshots, lists recorded ranges, forwards PTZ moves and preset recalls, presses the recorder's button rules, and polls the recorder's events so a person or vehicle on a camera becomes zone state and flags GEM can act on.

It is a snapshot source for the Access Activity investigation when an access device names it as its NVR, and is listed as evernvr in the device driver reference.

Prerequisites​

  • An EverNVR recorder reachable from the GEM controller over HTTPS. The recorder's own certificate is accepted.
  • An API token minted on the recorder (Settings → API), bound to the account GEM should act as. A read-only token bound to a viewer is enough for viewing and events; PTZ and button presses need a read-write token bound to an operator.

Live video​

When the recorder has RTSP switched on (Settings → RTSP streams on the recorder, EverNVR after 0.1.80), each zone plays the camera's own H.264 stream through GEM's relay in video mode: the real frame rate and resolution, remuxed rather than decoded, so no GPU is involved on the controller, and the recorder serves it without opening another camera connection. In auto the zone plays the camera's main stream when it is H.264, otherwise its sub stream when that is, otherwise the main stream (H.265, which GEM shows as stills). The URL is RTSPS when the recorder serves it, since it carries the token.

Without RTSP at the recorder, and for a camera with privacy masks (which the recorder never serves over RTSP, because the masks are not drawn on it), the zone plays the recorder's MJPEG: stills at the recorder's detection rate. Each zone's stream_source says which it is and why. Reload the device after switching RTSP on or off at the recorder.

Setup steps​

  1. On the recorder, Settings → API → New token. Bind it to the account whose cameras GEM should see, and copy the secret; it is shown once.
  2. Admin → Devices → New, pick the EverNVR driver. Enter the recorder's host, its port (443 unless it is published elsewhere) and the token.
  3. Save the device. On connect it reads the camera list and creates one zone per camera the token's account may see. Reload the device to pick up cameras added later; list_cameras prints what the recorder reports.

Attribute reference​

Device — required​

AttributeTypeDescription
ipstringRecorder hostname or IP.
tokenstring (secure)API token from the recorder, starting evk_.

Device — optional​

AttributeTypeDefaultDescription
portint443The recorder's port.
protocolstringhttpshttp only on a trusted network with a recorder on plain HTTP.
status_intervalint (ms)3000How often /api/events is polled. Blank or 0 means 3000; anything under 1000 is read as 1000.
rtsp_streamstringautoauto (see Live video), main or sub for that RTSP stream, or mjpeg to always play the recorder's MJPEG.

After connecting the driver writes recorder_version, acts_as (the account and role the token stands for) and camera_count on the device for reference.

Zone​

Zones are created automatically, one per camera; the zone address is the camera's id on the recorder. A camera the recorder lists without a name gets the label Camera <id>. The driver syncs these on every connect:

AttributeDescription
stream_urlLive RTSP(S) or MJPEG URL with the token as the password. Stored encrypted; never sent to a browser.
stream_modevideo for an RTSP stream, jpeg for MJPEG.
stream_sourceWhich recorder stream the zone plays, such as rtsp main (h264, 1920x1080), or mjpeg: and the reason.
has_ptztrue when the recorder can move the camera.
resolution, encoding, device_modelFrom the recorder's recording profile and camera details.

And these change as the recorder sees things:

AttributeDescription
statemotion while a visit is in progress, clear once the camera has no visit in progress (see Events for older recorders).
person, car, truck, bus, motorcycle, bicycle, dog, cat, …1 while a visit of that kind is in progress, 0 when the last one ends. A visit the recorder relabels before it ends (car, then truck) clears the flag it began with too. On an older recorder a flag clears itself after 120 s, even if the visit is still in progress.
last_motionWhen the last visit began, epoch milliseconds.
last_labelWhat the last visit was.
last_whoThe known name the recorder recognized, unrecognized, or blank when it did not judge.

Commands​

CommandNotes
snapshotA JPEG from the recording at datetime, or the live frame with no time. Returns {data, mime} like the other camera drivers.
thumbnailThe live frame.
recordingsRecorded ranges between start and stop.
get_eventsRecent visits, newest first, for the zone or the whole recorder.
web_linkA deep link to the recorder's playback at datetime, or its live view on the camera. A blank or unparseable time links to the live view.
up / down / left / right, moveA half-second nudge through the recorder's PTZ; move takes direction (up, down, left, right, in, out).
continuous_moveVelocities pan_speed, tilt_speed, zoom_speed from -1 to 1; the recorder stops the move itself after a short timeout. No velocities means stop.
stop, zoom_in, zoom_out, centercenter aims at a point in the picture, x and y from -1 to 1.
get_presets, goto_preset, load_preset, homeRecall by name, token, or number in the camera's list. The recorder never creates presets; make them on the camera.
get_buttons, press_buttonThe recorder's button rules the token may press. press_button matches the rule's id, label or name, case-insensitively; a blank name is refused (choose a button).

Every time argument (datetime, start, stop) reads the same way: a number below 1e12 is epoch seconds, a larger one epoch milliseconds, anything else is parsed as a date (ISO works best). A blank, whitespace-only or out-of-range time counts as no time, so snapshot returns the live frame and web_link the live view. recordings defaults stop to now and start to one hour before stop. A blank address counts as none: the command uses the zone's own camera, or answers camera address required when it has none.

The recorder never changes a camera's configuration, so there are no privacy-mask commands.

Events​

The driver polls /api/events every status_interval and walks new visits oldest first. On a recorder whose events carry updated_at (EverNVR releases after 0.1.69) it follows changedSince, which reports each visit when it begins and again when it ends, so a zone goes clear when the camera's last visit ends, even if newer visits started in between. A visit that begins and ends between two polls still sets last_motion and goes motion, then clear. An older recorder only reports visits by when they began, so the driver misses the end of a visit once a newer one has started, and takes any end it does see to mean the camera is clear. The driver switches by itself once the recorder is updated. A poll never starts while the previous one is still waiting for the recorder. When the recorder stops answering, or rejects the token, the driver polls less often, doubling the gap up to once a minute, and logs the failure once; the first answer brings it back to status_interval. A visit whose zone update fails to save is tried again on the next poll, up to three times, then skipped with a warning so later visits still arrive. Reaction time is the poll interval; sub-second reaction would need the recorder's WebSocket feed, which the driver deliberately does not hold open so a recorder restart never leaves a stale socket.

Troubleshooting​

SymptomCheck
The device stays disconnected with "rejected the API token"The token was revoked on the recorder or its account lost access. Mint a new one.
PTZ or press_button answers 403The token is read-only or bound to a viewer. Mint a read-write token bound to an operator.
Fewer zones than camerasThe token's account sees only some cameras; give it the rest under the recorder's Settings → Access and reload the device.
No live videoGEM's relay opens the stream URL from the controller itself; check the recorder is reachable from there (for RTSP, its RTSPS port, 8322 by default) and the token is live. Setting rtsp_stream to mjpeg and reloading rules RTSP out.
Live video is a slow series of stillsThe zone plays MJPEG (see stream_source). Switch RTSP on at the recorder and reload the device. A camera with privacy masks stays on MJPEG.
snapshot with a time answers 404No footage is kept for that moment, or the camera is in intelligence-only mode.