Axis Camera Station (Pro)
Connects GEM to an Axis Camera Station Pro NVR over its GraphQL API. The driver pulls the video-source inventory, creates a camera zone per source, streams live video, fetches snapshots and recordings, and forwards PTZ and privacy-mask commands to the cameras.
The driver is the snapshot source used by the
Access Log when an access device names it as its
NVR. It is also listed as axis_camera_station in the
device driver reference.
Prerequisites
- ACS Pro is licensed and reachable over HTTPS.
- An ACS local user with API access exists (ACS Pro client → Configuration → Security → User permissions).
- For PTZ-over-VAPIX and privacy masks (see below), each camera must be reachable on the LAN and have camera credentials set.
Setup steps
- Admin → Devices → New, pick the Axis Camera Station (Pro) driver.
- Enter the ACS host/IP, username, and password. Leave the port on
443unless ACS is published on another HTTPS port. - (Optional) Set
camera_username/camera_password— used as defaults when the driver calls VAPIX directly on individual cameras. The driver pre-creates both on the device the first time it connects (camera_usernameseeded toroot, the AXIS factory default;camera_passwordleft blank and secure), so they're visible to edit even if the first connection fails. When either is left blank the driver falls back to the ACS login for VAPIX calls. - Save the device. On connect it signs in, discovers the camera station, and creates one camera zone for every video source ACS reports — no command needed. Reload the device whenever you add or remove cameras in ACS to re-sync the zone list.
The driver runs an OAuth/PKCE sign-in against the ACS web-client endpoint and refreshes the token automatically.
The list_cameras command re-reads the in-memory source inventory and updates
the camera_count device attribute — handy to confirm ACS is reachable after a
change. It does not create zones; new cameras become zones on the next device
reload (which re-runs discovery).
Attribute reference
Device — required
| Attribute | Type | Description |
|---|---|---|
ip | string | ACS hostname or IP. |
username | string | ACS local username. |
password | string (secure) | ACS local password. |
Device — optional
| Attribute | Type | Default | Description |
|---|---|---|---|
port | int | 443 | HTTPS port. |
status_interval | int (ms) | 60000 | Status poll interval. |
camera_username | string | root | Default VAPIX username for all cameras. Blank falls back to the ACS login. |
camera_password | string (secure) | — | Default VAPIX password for all cameras. Blank falls back to the ACS login. |
After the first connect the driver also writes read-only diagnostic attributes on
the device for reference: camera_count, server_version, server_type, and the
ACS organization / resource-group identifiers (org_name, resource_group_name,
inventory_id, …). You don't set these — they confirm what GEM discovered.
Zone
Zones are created automatically when the device connects, one per ACS video
source. The zone address is the video-source ID assigned by ACS. (Reload the
device to pick up cameras added in ACS after the first connect.)
| Attribute | Type | Description |
|---|---|---|
camera_ip | string | Camera IP for direct VAPIX control (PTZ / privacy). Defaults to the address ACS reports for the camera. |
camera_username / camera_password | string | Per-zone VAPIX credentials. Resolution order: zone → device default → ACS login. Leave blank to inherit. |
imagesource | int | Sensor index on the physical camera (0-based), set automatically during discovery. Drives per-sensor VAPIX calls — see Multi-sensor cameras. |
stream_url, has_ptz, serial, device_model, product_type, device_name, resolution, encoding | — | Surfaced read-only during discovery. |
Commands
PTZ and privacy commands reach the camera by two different paths:
- Via ACS (PtzFacade): pan/tilt — the direction verbs
up/down/left/rightandmove— plusstop,zoom,center, and preset recall (home,goto_preset,load_preset,get_presets). These are addressed by the ACS camera ID, use the ACS login, and need nocamera_ipor per-camera credentials. The direction verbs are what the generic PTZ control UI emits (one verb per arrow);movetakes the same direction from adirectionarg for macros and API callers. Both resolve to the samePtzFacade.Movecall.load_presetrecalls a preset by number (the generic UI's preset buttons emit1–6); a numeric value is matched against the ACS preset list and a non-numeric value is used as the preset token directly. - Direct to the camera (VAPIX): zoom (
zoom_in/zoom_out),save_preset,continuous_move,query_position, and the privacy masks (privacy_on/privacy_off, also aliased asoff/on). ACS has no API for these, so they go straight to the camera and require the zone'scamera_ipand camera credentials.zoom_in/zoom_outtake an optionalsteparg (relative zoom, default100);save_presetstores the current position as the numbered preset given in itspresetarg.
Other commands include snapshot / multi_snapshot (live or from a recording at
a given time), recordings, thumbnail, web_link (a deep link to the ACS web
client), list_cameras, and refresh_token.
Privacy masks
privacy_on / off and privacy_off / on toggle a GEM-managed, full-frame
privacy mask on the targeted sensor — the default obscures the whole image.
Pass an optional mask argument to act on a single named mask instead.
GEM matches the mask by its name (trimmed, case-insensitive) among the masks
already configured on that sensor and flips only that mask on or off — the
GEM full-frame mask and every other mask are left untouched, and the named
mask's geometry is preserved (only its enabled state changes). The command
returns an error if no mask with that name exists on the sensor.
| Command | mask omitted | mask set |
|---|---|---|
privacy_on / off | Enable the GEM full-frame mask. | Enable only the named mask. |
privacy_off / on | Disable the GEM mask and switch off any other masks still enabled on the sensor. | Disable only the named mask. |
Use named masks to drive partial privacy zones an installer pre-drew on the camera (e.g. a single window or doorway) from a macro or schedule, without disturbing the camera's other masks.
Multi-sensor cameras
Multi-sensor / panoramic models (e.g. the AXIS P4705-PLVE) expose several sensors
behind a single IP. ACS lists one video source per sensor, so GEM creates one
zone per sensor and records each sensor's index in the read-only imagesource
zone attribute (0 for the first or only sensor).
Because the VAPIX PTZ and privacy APIs hit the shared physical camera IP, the
driver uses imagesource to target the correct sensor:
- PTZ —
continuous_moveandquery_positionderive the VAPIX video channel fromimagesource(channel =imagesource+ 1, sinceptz.cginumbers cameras from 1). Pass an explicitchannelarg to override. - Privacy masks — masks are added, removed, and named per image source, so a
mask on one sensor does not collide with or shadow a mask on another.
privacy_offremoves the GEM-managed mask and switches off any other privacy masks still enabled on that sensor, so the image is fully visible. Those extra masks are disabled (Enabled=no), not deleted — an operator can re-enable a manual mask from the camera's own web UI.
Single-sensor cameras resolve to imagesource 0 / channel 1, identical to the
previous behavior — no configuration change is needed.
PTZ and privacy commands only act on the sensor whose zone you target. To control every sensor of a panoramic camera, issue the command on each sensor's zone.
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Login fails / token never refreshes | The ACS user lacks API access, or HTTPS is unreachable on the configured port. Token validation is time-sensitive — check server clock skew. |
| Snapshots / streams return 401 | The forwarded stream token expired. Run the refresh_token command on the device (or reload it) to re-issue. Token validation is time-sensitive — check server clock skew. |
| Pan/tilt or preset recall does nothing | These go through ACS (PtzFacade). Confirm the camera supports PTZ (has_ptz on the zone) and that the ACS user has PTZ permission on it. |
Zoom or save_preset returns an auth error | zoom_in / zoom_out / save_preset (and continuous_move / query_position) go directly to the camera over VAPIX. Set the zone's camera_ip (auto-populated by list_cameras) plus camera credentials. |
Privacy command returns camera authentication failed (HTTP 401/403) | The camera rejected the VAPIX login. Set camera_username / camera_password on the zone or device (they default to the AXIS root account / the ACS login). Privacy commands now report this error instead of falsely reporting success. |
list_cameras returns empty | The ACS API user cannot see the camera. Grant the user visibility in the ACS Pro client. |
| PTZ or privacy hits the wrong sensor on a panoramic camera | Confirm each sensor's zone has the correct imagesource. Reload the device to re-run discovery and repopulate it, or pass an explicit channel arg on PTZ commands. |