I own a new Hikvision camera and couldn’t find a reported PTZ control solution for HA that worked. I created one using the rest_command
integration and some ISAPI manual I found.
PTZ via ONVIF not working (situation March 2020)
There is the usual way to enable ONVIF in your camera settings, but that way wasn’t working for me in HA 0.106.x in the first place and - as I understood - is working for less people since HA 0.107.x. I’m sure there will be a solution for ONVIF sooner or later, but in the meantime I couldn’t control PTZ via HA. Luckily you can make it work using rest_commands.
Description of my situation
- I have NO issue with streaming the video image in HA.
- When performing a call to the (new) service
onvif.ptz
there is a “PTZ actions are not supported
” in the logs of HA. - I’m running HA 0.107.4 on HassIO.
- The camera is a Hikvision mini PTZ camera model DS-2DE2A404IW-DE3. (Please report if the solution also works for other Hikvision models.)
Requirements for the solution
- You have to have knowledge about
curl
or be able to use Postman to tweak the solution in a way that it is working in your situation / for your camera model. - In your camera settings enable “digest/basic” verification for Web. In my cam settings the menu path is: Configuration > System > Security > Verification > Web verification. Otherwise authorization will fail.
- In your camera settings create an extra user: Configuration > System > User management > User management > Add. Choose for the level of ‘operator’ and check if ‘Remote PTZ control’ is enabled for this new user. The username and password are referred to as PTZ_USER_NAME and PTZ_PASSWORD in the description below.
- Have your IP address of the camera at hand. It’s referred to as IP_OF_CAMERA in the description below.
The solution
There are some rest_command
s, script
s, some customized icons and of course a picture-glance
card with the PTZ controls on it.
The rest_commands
I made two rest_command
s. The first one is needed for the basic PTZ commands like pan left/right, tilt up/down and zoom in/out. The second command is to easily move back to a default ‘zero position’. See the star icon in the image.
In the comments #
I wrote down all the minimal and maximal values. These values differ per camera model. I found mine by requesting it to the camera:
(GET) http://PTZ_USER_NAME:PTZ_PASSWORD@IP_OF_CAMERA/ISAPI/PTZCtrl/channels/1/capabilities
The duration is in milliseconds. You can choose of course another value here.
rest_command:
# pan: -100..100, tilt: -100..100, zoom: -100..100, duration: in msecs
cam04_ptz_momentary:
url: http://IP_OF_CAMERA/ISAPI/PTZCtrl/channels/1/Momentary
method: PUT
payload: '<PTZData>
<pan>{{ pan }}</pan>
<tilt>{{ tilt }}</tilt>
<zoom>{{ zoom }}</zoom>
<Momentary>
<duration>500</duration>
</Momentary>
</PTZData>'
username: PTZ_USER_NAME
password: PTZ_PASSWORD
content_type: 'application/xml'
verify_ssl: false
# azimuth: 0..3300, elevation: 0..900, absoluteZoom: 10..40
cam04_ptz_absolute:
url: http://IP_OF_CAMERA/ISAPI/PTZCtrl/channels/1/Absolute
method: PUT
payload: '<PTZData>
<AbsoluteHigh>
<azimuth>{{ azimuth }}</azimuth>
<elevation>{{ elevation }}</elevation>
<absoluteZoom>{{ absoluteZoom }}</absoluteZoom>
</AbsoluteHigh>
</PTZData>'
username: PTZ_USER_NAME
password: PTZ_PASSWORD
content_type: 'application/xml'
verify_ssl: false
The scripts
There is a script per PTZ action. The values used in the data
element have to adhere the minimal and maximal values you found earlier.
The values for the last script (the zero positioning script) can be found by trial and error. Or find them by moving the PTZ to the desired position via the camera UI and use the response of this request:
(GET) http://PTZ_USER_NAME:PTZ_PASSWORD@IP_OF_CAMERA/ISAPI/PTZCtrl/channels/1/status
script:
cam04_pan_left:
alias: 'Cam4 pan left'
sequence:
- service: rest_command.cam04_ptz_momentary
data:
pan: -50
tilt: 0
zoom: 0
cam04_pan_right:
alias: 'Cam4 pan right'
sequence:
- service: rest_command.cam04_ptz_momentary
data:
pan: 50
tilt: 0
zoom: 0
cam04_tilt_up:
alias: 'Cam4 tilt up'
sequence:
- service: rest_command.cam04_ptz_momentary
data:
pan: 0
tilt: 75
zoom: 0
cam04_tilt_down:
alias: 'Cam4 tilt down'
sequence:
- service: rest_command.cam04_ptz_momentary
data:
pan: 0
tilt: -75
zoom: 0
cam04_zoom_in:
alias: 'Cam4 zoom in'
sequence:
- service: rest_command.cam04_ptz_momentary
data:
pan: 0
tilt: 0
zoom: 100
cam04_zoom_out:
alias: 'Cam4 zoom out'
sequence:
- service: rest_command.cam04_ptz_momentary
data:
pan: 0
tilt: 0
zoom: -100
cam04_ptz_zero:
alias: 'Cam4 PTZ zero position'
sequence:
- service: rest_command.cam04_ptz_absolute
data:
azimuth: 1500
elevation: 0
absoluteZoom: 10
Icon customization
I gave each script an icon. That’s better for reuse.
But of course you can skip this an put an icon directly in the picture-glance
card if you want.
homeassistant:
customize:
script.cam04_pan_left:
icon: 'mdi:arrow-left-bold-circle-outline'
script.cam04_pan_right:
icon: 'mdi:arrow-right-bold-circle-outline'
script.cam04_tilt_up:
icon: 'mdi:arrow-up-bold-circle-outline'
script.cam04_tilt_down:
icon: 'mdi:arrow-down-bold-circle-outline'
script.cam04_zoom_in:
icon: 'mdi:magnify-plus'
script.cam04_zoom_out:
icon: 'mdi:magnify-minus'
script.cam04_ptz_zero:
icon: 'mdi:star-circle-outline'
The card
Finally the picture-glance
card to make it all visible in Lovelace.
- type: picture-glance
title: Cam4 Front garden
camera_image: camera.cam04
entities:
- entity: script.cam04_pan_left
tap_action:
action: call-service
service: script.cam04_pan_left
- entity: script.cam04_tilt_up
tap_action:
action: call-service
service: script.cam04_tilt_up
- entity: script.cam04_tilt_down
tap_action:
action: call-service
service: script.cam04_tilt_down
- entity: script.cam04_pan_right
tap_action:
action: call-service
service: script.cam04_pan_right
- entity: script.cam04_zoom_in
tap_action:
action: call-service
service: script.cam04_zoom_in
- entity: script.cam04_zoom_out
tap_action:
action: call-service
service: script.cam04_zoom_out
- entity: script.cam04_ptz_zero
tap_action:
action: call-service
service: script.cam04_ptz_zero
tap_action:
action: more-info
Maybe my solution doesn’t work for you
I’ll write down briefly how I found the solution, because my solution above maybe is working for my camera model only.
There is a 700+ page manual at Hikvision that didn’t give me the solution right away, but did give enough hints on page 86 to search further. I found another manual dated 2013 on a Russian FTP server: IP Surveillance API PTZ Service Specification. In this second manual you’ll find the specification to send requests to your camera to control PTZ. You can test it e.g. using curl
or an app like Postman.
Extending this solution
There are endless possibilities to extend. E.g. you can make use of the ‘presets’ of the camera instead of having to maintain the values for the ‘zero position’ in HA scripts. Or maybe you could make a template sensor to get the PTZ coordinates into HA and do something with it there.