Hikvision (ISAPI)
GEM controls Hikvision IP cameras and NVRs through the public ISAPI (Integrator Standard API) over HTTP/HTTPS with digest authentication. ISAPI is supported on essentially all modern Hikvision-branded firmware as well as several OEMs (LTS, Hilook, etc.).
For each camera or NVR you add one device; for each video channel you add one zone. A standalone IP camera is a single zone with address = 1.
Prerequisites
- A Hikvision device user account with at least Operator privilege.
- For PTZ commands, the user account must additionally have PTZ permission on the channel — Operator alone is not sufficient.
- ISAPI must be enabled on the device. It is enabled by default on all current firmware; some locked-down installs disable it.
Setup
- Add a new device of type Hikvision (ISAPI) under System → Devices.
- Set:
- Device IP — LAN IP of the camera or NVR.
- Username / Password — local device credentials. The password is stored as a secure attribute.
- Leave Port / Scheme at defaults (
80/http) for most installs. Switch tohttps(port443) if the device only exposes HTTPS.
- Save and reload. The driver will hit
/ISAPI/System/deviceInfoon connect; success is logged and the device is marked online. - Add zones:
- For an NVR, run
get_channelsfirst to enumerate input channels, then add a zone per channel withaddress = 1,2,3, … - For a single IP camera, one zone with
address = 1is enough.
- For an NVR, run
- Optionally set the zone-level
streamattribute tosubto use the lower-resolution stream for snapshots; default ismain.
Attribute reference
Device attributes
| Attribute | Required | Type | Default | Notes |
|---|---|---|---|---|
ip | yes | string | — | LAN IP of the camera or NVR |
username | yes | string | — | Local device account |
password | yes | string (secure) | — | Local device password |
port | no | int | 80 | TCP port for ISAPI (443 for HTTPS) |
scheme | no | enum | http | http or https |
auth_mode | no | enum | digest | Use basic only for very old firmware |
status_interval | no | int | 60000 | Liveness poll period (ms) |
Zone attributes
| Attribute | Required | Type | Notes |
|---|---|---|---|
address | yes | string | Channel number, e.g. 1, 2, 3 |
stream | no | enum (main/sub) | Picks ISAPI ddss stream id; defaults to main |
stream_url | no | string | Optional RTSP/HTTP URL for live preview widgets |
Channel id format
ISAPI uses a 3-digit ddss channel id in URLs, derived from the channel number:
| Human channel | Stream | ISAPI channel id |
|---|---|---|
| 1 | main | 101 |
| 1 | sub | 102 |
| 2 | main | 201 |
| 8 | main | 801 |
The driver converts your zone address (the human channel number) to the ddss form automatically. You only ever supply the human number.
Commands
| Command | Args | Notes |
|---|---|---|
snapshot | address | Returns {content_type: 'image/jpeg', base64: '…'}. Honors zone stream attribute. |
ptz_pan_tilt | address, pan, tilt | Continuous PTZ; pan/tilt are -100..100. |
ptz_zoom | address, zoom | Continuous zoom; -100..100. |
ptz_stop | address | Sends {pan:0, tilt:0, zoom:0} continuous PTZ to halt motion. |
ptz_preset | address, preset | Recall preset id 1-255. |
get_channels | — | NVR: lists /ISAPI/ContentMgmt/InputProxy/channels. IP camera: falls back to /ISAPI/Streaming/channels. |
get_device_info | — | Raw response of /ISAPI/System/deviceInfo (model, firmware, serial). |
Auth model
The driver uses HTTP digest authentication by default — opts.auth = {username, password, sendImmediately:false} against the shared generic_http base. The base library handles the 401 → digest handshake transparently.
If a device runs older firmware that only supports basic auth (you'll see WWW-Authenticate: Basic in the 401), set auth_mode to basic.
Known limitations
- No event subscription yet.
/ISAPI/Event/notification/alertStream(long-lived chunked event push) is not wired in this driver. Liveness polling ondeviceInfois the only background traffic. - No motion / tampering / line-cross hooks. When events land, integrators will surface those as zone attributes.
- PTZ continuous self-stops on most firmware after a few seconds. Always issue
ptz_stopfor predictable behavior. - No relative PTZ. Only
continuousandpresetPTZ paths are exposed; relative PTZ (/ISAPI/PTZCtrl/channels/{id}/relative) is a future addition.
Troubleshooting
| Symptom | Likely cause |
|---|---|
All requests return 401 | Wrong credentials, account locked after repeated failures, or user lacks the Operator role. Hikvision locks accounts after ~5 wrong attempts. |
snapshot returns 404 | Zone address does not match an enabled input channel. Run get_channels to confirm. |
| PTZ commands return 403 | Operator privilege is not enough — the user account needs explicit PTZ permission on that channel. |
| Works on http but not https | Self-signed certs are tolerated by default. If https still fails, the device may only listen on the alternate port (commonly 443 vs 8443). |
| Sporadic timeouts on NVRs | NVRs can be slow under load; raise status_interval to reduce poll pressure. |
Wire format reference
GET /ISAPI/System/deviceInfo Authorization: Digest …
GET /ISAPI/ContentMgmt/InputProxy/channels (NVR)
GET /ISAPI/Streaming/channels (single camera fallback)
GET /ISAPI/Streaming/channels/101/picture → JPEG bytes
PUT /ISAPI/PTZCtrl/channels/101/continuous
<PTZData><pan>40</pan><tilt>0</tilt><zoom>0</zoom></PTZData>
PUT /ISAPI/PTZCtrl/channels/101/presets/3/goto