Reolink Cameras and NVRs
Reolink cameras and NVRs that expose the public /cgi-bin/api.cgi JSON API on the LAN. The driver polls per-channel motion and AI detection state, captures snapshots, drives PTZ, and toggles spotlight and siren accessories.
Prerequisites
- Reolink camera or NVR with firmware that exposes the JSON API. Most cameras shipped from 2018 onward qualify; older firmwares only expose the legacy CGI interface and are out of scope.
- A non-default admin (or operator) account on the device. The driver authenticates via
Login, which is rate-limited — a long string of bad password attempts will lock the account for several minutes. - TCP access to the camera's HTTP port (default 80) from the GEM controller. Some battery-powered models (Argus, Go) only accept the JSON API over HTTPS on port 443; set the
protocolandportattributes accordingly.
Setup
- Confirm the camera is reachable from GEM. Browsing to
http://<camera-ip>/cgi-bin/api.cgi?cmd=Loginshould return a JSON envelope (an error envelope is fine — it confirms the API is alive). - Create the device row in System → Devices with driver
reolink. - Set the required attributes (see table below) and save. The driver will run
Loginfollowed byGetDevInfoand log the model + channel count on success. - Run the
get_channelscommand to print the per-channel ids and names. - Create one zone per channel under the device. Set the zone
addressto the channel index —0for a single camera,0..N-1for an NVR.
Required attributes
| Attribute | Description |
|---|---|
ip | LAN IP or hostname of the camera or NVR. |
username | Camera / NVR account. Operator-level minimum; admin recommended. |
password | Camera / NVR account password. Stored encrypted. |
Optional attributes
| Attribute | Default | Description |
|---|---|---|
port | 80 | HTTP(S) port. 443 for HTTPS-only models. |
protocol | http | http or https. Battery-powered models usually require https. |
status_interval | 5000 | How often (ms) to poll motion / AI state per channel. Keep ≥ 2000 ms. |
request_timeout | 8000 | Per-request timeout (ms). |
Zone address format
The zone address is the channel index as a string: "0" for a single camera, "0".."N-1" for an NVR (where N is channelNum from GetDevInfo).
Per-zone optional attributes:
| Attribute | Description |
|---|---|
ai_types | Comma-separated list of AI types to monitor on this channel (people, vehicle, dog_cat, face). Empty = all reported. |
Commands
| Command | Args | Notes |
|---|---|---|
login | — | Force a fresh Login and refresh the cached token. |
logout | — | Invalidate the current token. |
get_dev_info | — | Print device model, firmware, and channel count. |
get_channels | — | List channels (id, name, online). Use this to populate zone addresses. |
snapshot | address | JPEG snapshot for a channel. Returns {channel, length, contentType, base64}. |
get_motion | address | One-shot motion-detection state for a channel. |
get_ai_state | address | One-shot AI state (people / vehicle / dog_cat / face). |
ptz | address, op, speed, duration | PTZ control. op: Up/Down/Left/Right/LeftUp/RightUp/LeftDown/RightDown/ZoomInc/ZoomDec/FocusInc/FocusDec/Auto/Stop. speed 1-64. duration ms — driver auto-issues Stop afterwards. |
ptz_preset | address, preset, speed | Recall a PTZ preset (1-64). |
spotlight_on / spotlight_off | address | White-light spotlight (camera must have one). |
siren | address | One-shot audible alarm. |
reboot | — | Reboot the device. The exact envelope on older NVR firmware has not been verified against hardware. |
Status polling
For every zone with a numeric address, the driver polls:
GetMdState→ writesmotion(1/0) and a derivedstate(motion/clear) attribute to the zone whenever the value changes.GetAiState→ writes a comma-separatedai_detectedattribute (e.g.people,vehicle) when any AI type is alarming.
Cameras without AI return a rspCode error for GetAiState, which the driver swallows. Polling is throttled by status_interval (default 5 s).
Token lifecycle
Login returns an opaque token with a 3600 s default lease. The driver refreshes 60 s before expiry and on demand whenever an API call returns one of the auth-related Reolink rspCodes. A manual logout command invalidates the token immediately.
Known limitations
- Only the JSON API is wired. Reolink's older
/api/v1and ONVIF interfaces are out of scope (use the existingonvifdriver for ONVIF events). - Some commands (
reboot,siren) are accepted by every camera tested in the wild but the exact envelope on older NVR firmware has not been verified against hardware. They are exposed; let us know if a specific model rejects them. - RTSP / RTMP streaming is not handled here — use GEM's existing camera streaming subsystem with the camera's standard
rtsp://<ip>:554/h264Preview_01_mainURL. - Subscription-style event push (HTTP webhook on motion) is not implemented. The driver polls instead.
Troubleshooting
| Symptom | Check |
|---|---|
login failed | Confirm the username and password in the Reolink mobile app. Repeated bad attempts lock the account for several minutes. |
rspCode -6 / -7 | Token expired or invalidated by another session. The driver auto-recovers; persistent failures usually mean two clients are racing on Login. |
snapshot rejected (token / auth) | Older firmware returns the web UI HTML when the token is rejected. The driver detects this and reports the error; trigger a reconnect or rotate the password. |
| Motion never fires | Confirm motion detection is enabled on the channel and a detection zone is configured in the Reolink app. |
| Battery camera fails to connect | Switch protocol to https and port to 443. |