Dahua Joystick PTZ Control

Intro

This is just a mini tutorial on how to use the Dahua HTTP API and Python (pygame) to control a Dahua PTZ camera. Tested it on a Dahua SD1A404XB-GNR and a Dahua SD49425XB-HNR. It may work on HikVision and Amcrest cameras as well, although i have not tested that (the API looks the same)

This joystick script is part of a larger project i’m working on which is made up by modules and one of these modules requires control over the PTZ functions of a Dahua camera. Specifically the Continuously function of the Dahua HTTP API

Dahua API

Looking at the Dahua HTTP API PDF documentation they offer two types of movement

  • PTZ Basic Movement
    • issued by the start action
    • code indicates direction (Up, Down, Left, Right)
    • to stop issue a stop action
    • example request
      • http://192.168.1.108/cgi-bin/ptz.cgi?action=stop&code=Up&channel=1&arg1=0&arg2=0&arg3=0
  • PTZ Continuously Moving
    • issued by start action
    • arg1
      • positive values – turn right
      • negative values – turn left
    • arg2
      • positive values – move down
      • negative values – move up
    • arg3
      • positive values – zoom out
      • negative values – zoom in
    • arg4
      • duration (unused)
    • to stop issue a stop action
      • opted for just issuing arg0=0, arg1=0, arg2=0, arg3=0
    • example request:
      • http://192.168.1.108/cgi-bin/ptz.cgi?action=start&code=Continuously&channel=1&arg1=5&arg2=5&arg3=5&arg4=60

Obviously i needed the Continuously moving type, this will send all of the desired movement arguments in a sequence to the camera.

Joystick

Now let’s move onto the joystick. It can be any kind of joystick plugged in to USB or Bluetooth. The controller i’m using is a PS3 controller from AliExpress which can be acquired for less than € 10,-

This controller has 6 axes and 17 buttons so i needed to find out which axes belongs to which movement. For that i used a program called jstest-gtk for Linux. From there i could determine that:

  • Left stick
    • axis 0 controls left and right
    • axis 1 controls up and down
  • Right stick
    • axis 3 controls left and right
    • axis 4 controls up and down

Was thinking what would be the most instinctive (for me at least) control layout and came up with the following. For controlling the camera’s movement

For controlling the camera’s zoom capabilities.

The script also has some button actions mapped. When pressed these buttons activate the camera’s presets. The x_button initiates preset 1, square_button initiates preset 2 and so on.

Enough talking, show me the code 😀

Code

Okay let’s jump right in and my code from Github

git clone https://github.com/wvthoog/Dahua-Joystick-PTZ-Control.git

Then install the dependencies. Preferably within a virtual environment ( python -m venv venv )

pip install -r requirements.txt

This will install the pygame and requests libraries.

Before launching the script you probably need to change a couple of values in the script itself. Namely these values:

# Camera settings
ip = '192.168.2.21'         # change
username = 'admin'          # change
password = '12345678910'    # change
channel = 1

Speaks for itself, but here are some pointers anyway. Change ip to the IP address of your camera, change the username to a username which has PTZ control permissions and lastly change the password with the password for that user. And you’re practically done. You can now fire up the script with a joystick connected to your computer

python dahua_joystick.py

Additional parameters

Some minor tuning can also be done by adjusting these values. The threshold value is the minimal value to be registered before the code detects movement from both sticks. Increase if you feel that the camera moves too quickly when pushing the sticks. (max is 1)

The movement_multiplier controls how fast the camera moves in either direction. I’ve set it to 10 because that value best suits my needs. Decrease if you want movements to be slower, increase for faster. Same goes for zoom_speed_multiplier, increasing the value increases the zoom-in and zoom-out speed.

# Joystick settings
threshold = 0.1
movement_multiplier = 10
zoom_speed_multiplier = 100

Button mapping

Under the same joystick settings you find the button mappings. You can change those if they are different in your setup

x_button = 0
square_button = 3
triangle_button = 2
circle_button = 1

Presets

It is also possible to change which preset is activated when a certain button is pressed.

                # Define actions for each button
                if button_pressed == x_button:  # X Button
                    print("X Button pressed. Performing preset action...")
                    preset_number = 1

                elif button_pressed == circle_button:  # Circle Button
                    print("Circle Button pressed. Performing preset action...")
                    preset_number = 4

In this part of the code when the x_button is pressed preset 1 will be activated on the camera, when circle_button is pressed preset 4 will be activated. Change the settings to your liking or perhaps add some more presets and add additional elif statements for that.

ToDo

  • Maybe add stop action command if this code gives me issues

PayPal

If you like my work, please consider supporting.