ArtsAutosBooksBusinessEducationEntertainmentFamilyFashionFoodGamesGenderHealthHolidaysHomeHubPagesPersonal FinancePetsPoliticsReligionSportsTechnologyTravel

ONVIF Programming Revealed

Updated on November 14, 2013

The starting point

This page is about ONVIF PHP implementation. I propose a simple solution to build Network Video Client (NVC) working with Network Video Transmitter devices (NVT) such as IP-cameras and video encoders. This solution is a simple programming exercise and has no claim to completeness. I choose PHP as programming language because it has almost no learning curve and is very simple to translate in other languages. ONVIF seems to have a very promising future, but the programming of a compliant client is not a simple task. It is very difficult to find examples and information to develop in a reasonable time frame. SOAP communication used by ONVIF is based on messages too heavy and complex and this adds further complexity. All this is not ideal to develop at an acceptable cost or at the experimental level. My goal here is to overcome these limitations and provide a solution to start development in time close to zero. I leave to the competence of reader any other improvement. At the moment of writing (March 2013), this is the first open-source PHP implementation of a NVC ONVIF-compliant.

PHP Programming Innovation Award Winner

PHP ONVIF is the winner of the PHP Programming Innovation Award among all the classes

nominated in the PHP Classes site during the month of April of 2013.

My Workbench

What I used, and you should too

The tools that I used are:

- ONVIF Device Manager: a NVC to manage NVT and Network Video Analytics (NVA) devices. I suggest you download and use this software. However, this software is not strictly necessary.

- Wireshark: a powerful network protocol analyzer. Wireshark is useful to analyze XML requests and responses between ONVIF Device Manager and NVT devices. Use Wireshark if you know exactly what to do, otherwise it is useless. However, this software is not strictly necessary.

- PHP version 5.3 with php5-curl extension installed. Obviously, this software is essential.

Consider that my programming is not exactly SOAP conformant. I'm not using any SOAP libraries. I'm working at low level using prepackaged sniffed messages dynamically adapted.

First steps

The security token could not be authenticated or authorized. Probably you already caught this error message in your code. No doubt, it is very difficult to find a working sample. In addition, ONVIF Recommendations don't help to quickly start a development. The Internet is full of forums with help requests, but there are few good solutions. Fortunately, I have the solution here. I tested my code with multi-brand video encoders and ip cameras based on ONVIF versions 1.0.2, 2.0, 2.0.1.

First of all, my code is in the form of a PHP class that should be embedded into your application alongside other core functionality. PHP class offers an abstraction layer very useful in this context, you can deal with ONVIF without waste your time with SOAP and other details. In the next sections, I share this class with you.

Feel free to cut & paste, download, use and extend my code in your applications. Any comments and code improvement is always welcome.

Please don't consider definitive my code. It's a starting point not a landing point. My needs required me to use a low level solutions to send SOAP messages. More elegants approaches can be adopted with higher level libraries (for example NuSOAP - SOAP Toolkit for PHP could be a valid resource for that job).

The PHP ONVIF Library

Code name "ponvif"

You can download the library by following the link in the section Resources.

The installation is very simple: copy the downloaded file in a folder, untar it.

To use the library in your code: make a text file and copy inside the following code:

<?php

require 'lib/class.ponvif.php';

$test=new ponvif();

$test->setUsername('HERE_NVT_USERNAME');

$test->setPassword('HERE_NVT_PASSWORD');

$test->setIPAddress('HERE_NVT_IPADDRESS');

$test->initialize();

?>

That's all! You have to instantiate an object (in this case $test) and call three functions to configure username, password and ip address about NVT. Username and password are account data configured on the NVT device. The ONVIF standard introduces four user levels: administrator, operator, media user and anonymous. Each user is assigned to a level in order to make authorization decisions related to the requests. To start, it's advisable to assign administrator level to the user used into your NVC.

You also need the IP address (or hostname) of the NVT device. Consider that the ONVIF protocol provides automatic device discovery but this feature is not covered in ponvif.

The function initialize() executes a bunch of requests for synchronization and authentication.

Synchronization is obtained sending the GetSystemDateAndTime ONVIF request. This request doesn't require authentication and is important because helps NVC to adjust its time with NVT time to send subsequent consistent messages. For authentication to work, it is important to have the same time in device and client so the timestamp in messages is not off with too much (e.g. 5 seconds).

After Synchronization, the ponvif instance is able to make authenticated requests. Authentication is based on Digest Authentication. Many people think of Digest Authentication as a protocol that is used with Web browsers for authenticating users browsing the Internet. However, Digest Authentication is also a general purpose protocol that can be used for authentication at different levels. ONVIF, for example, uses Digest Authentication as a security mechanism to consume web services. This is how the authentication algorithm coded in ponvif works:

  • The client begins with the two pieces of information: the username and password.
  • The client creates a nonce, which is a cryptographically random string.
  • The client creates a creation timestamp with the current time.
  • The Password Digest is created by creating an SHA1 hash of the combination of the nonce, timestamp, and password with the result BASE 64 encoded.
  • The combination of the nonce and timestamp would prevent the header from being reused.
  • The client sets a header in every request containing the username and digest.
The function initialize() completes its job sending other requests: GetCapabilities, GetProfiles and GetVideoSources. By sending a GetCapabilities request, NVC can find out all capabilities of a NVT device. The capability list includes references to the addresses (XAddr) of the service implementing the interface operations in the following categories: All, Analytics, Device, Events, Imaging, Media and PTZ. In addition, GetProfiles and GetVideoSources provide data about available video sources and other useful details required to make further requests.

initialize() also collects a subset of important info in a special array named "sources", you can get this array using the function getSources(). An example of array returned by getSources() is below:

Array

(

 [0] => Array

  (

   [sourcetoken] => cam0

   [0] => Array

   (

    [profiletoken] => defaultPrimary0

    [encoding] => H264

    [width] => 720

    [height] => 576

    [fps] => 5

    [bitrate] => 290

    [ptz] => Array

    (

     [name] => Vicon Extended default config

     [nodetoken] => ptz15

    )

   )

  )

)

The data included in the array are important for us to make further requests. I highlighted the data that we'll reuse. In addition, ponvif offers other special functions to setup a proxy (if your NVC is behind a proxy server), get/set attributes, etc.. Here the list:

  • setProxyHost($proxyHost): sets the proxy host (ip address or hostname) to connect to
  • getProxyHost(): gets current proxy host
  • setProxyPort($proxyPort): sets the proxy port
  • getProxyPort(): gets current proxy port
  • setProxyUsername($proxyUsername): sets the username required for proxy authentication
  • getProxyUsername(): gets current username for proxy authentication
  • setProxyPassword($proxyPassword): sets the password required for proxy authentication
  • getProxyPassword(): gets current password for proxy authentication
  • getUsername(): gets current username for NVT authentication
  • getPassword(): gets current password for NVT authentication
  • setDeviceUri($deviceUri): forces setting of ONVIF core web service URI
  • getDeviceUri(): gets current ONVIF core web service URI
  • getMediaUri(): gets current ONVIF media web service URI (as acquired by GetCapabilities)
  • getPTZUri(): gets current ONVIF ptz web service uri (as acquired by GetCapabilities)
  • getMediaUri(): gets current ONVIF media web service URI (as acquired by GetCapabilities)
  • getSupportedVersion(): returns an array containing major and minor of ONVIF version supported by NVT
  • getIPAddress(): gets current NVT ip address (or hostname)

Dealing with ONVIF requests

"Do complicated things in a simple way!"

ponvif offers an extended list of functions to send ONVIF requests. All of these functions correspond one-to-one to a request with the same name in the ONVIF protocol. Remember that ponvif covers only a subset of enormous set of ONVIF primitives. I hope to gradually increase this coverage. For this, your contribution may be important, so don't hesitate to post comments. First, we start from a small piece of sample code. Next, we complete with a list of supported requests and related ponvif functions. The sample code:

<?php

require 'lib/class.ponvif.php';

$test=new ponvif();

$test->setUsername('HERE_NVT_USERNAME');

$test->setPassword('HERE_NVT_PASSWORD');

$test->setIPAddress('HERE_NVT_IPADDRESS');

$test->initialize();

print_r($test->GetVideoSources());

print_r($test->GetProfiles());

print_r($test->GetCapabilities());

$sources=$test->getSources();

print_r($sources);

echo 'Media url: '.$test->getMediaUri()."\n";

echo 'Device url: '.$test->getDeviceUri()."\n";

echo 'Ptz url: '.$test->getPTZUri()."\n";

print_r($test->getSupportedVersion());

print_r($test->core_getDeviceInformation());

print_r($test->media_GetServices());

$profileToken=$sources[0][0]['profiletoken'];

$ptzNodeToken=$sources[0][0]['ptz']['nodetoken'];

echo $test->media_GetStreamUri($profileToken)."\n";

print_r($this->ptz_GetNode($ptzNodeToken));

$presets=$test->ptz_GetPresets($profileToken);

// get preset token of first preset

$presetToken=$presets[0]['Token'];

echo "$presetToken\n";

print_r($test->ptz_ContinuousMove($profileToken,"0.5","0"));

print_r($test->ptz_Stop($profileToken,"false","true"));

print_r($test->ptz_ContinuousMove($profileToken,"-0.5","0"));

print_r($test->ptz_Stop($profileToken,"false","true"));

// reset position to preset got previously, example usage of isFault

if (!$test->isFault($test->ptz_GotoPreset($profileToken,$presetToken,"0","0","0"))) echo "GotoPreset executed successfully\n";

?>

I use this code as unit test module. Consider that some requests or functionality should be supported from your NVT device. For example, I tested the code with an Aviglion ENC-4P-H264 connected to a PTZ analogic camera, and it worked like a charm. As you can see in the sample, I added a simple function isFault() to rapidly check if response contains a fault. A Fault indicates that something is not successful (probably your NVT doesn't support a request or other). Now, it's the moment to list supported ONVIF requests and related ponvif functions:

  • ONVIF Core Specification
    • core_GetSystemDateAndTime(): gets the device system date and time
    • core_GetCapabilities(): provides a backward compatible interface for the base capabilities
    • core_GetDeviceInformation(): gets device information, such as manufacturer, model and firmware version from a device
  • ONVIF Media Service Specification
    • media_GetStreamUri($profileToken, $stream, $protocols): requests a URI that can be used to initiate a live media stream using RTSP as the control protocol
    • media_GetServices(): gets a full set of capabilities
    • media_GetVideoSources(): lists all available video sources for the device
    • media_GetProfiles(): gets all existing media profiles
  • ONVIF PTZ Service Specification
    • ptz_GetPresets($profileToken): returns the saved presets
    • ptz_GetNode($ptzNodeToken): this function returns the properties of the requested PTZ node, if it exists. Use this function to get maximum number of presets, ranges of admitted values for x,y,zoom,iris,focus
    • ptz_GotoPreset($profileToken, $presetToken, $speedPantiltX, $speedPantiltY, $speedZoom_x): this function recalls a previously set preset. If the speed parameter is omitted, the default speed of the corresponding PTZ configuration shall be used. The GotoPreset command is a non blocking operation and can be interrupted by other move commands
    • ptz_RemovePreset($profileToken, $presetToken): this function removes a previously set preset
    • ptz_SetPreset($profileToken, $presetName): this function saves the current device position parameters so that the device can move to the saved preset position through the ptz_GotoPreset function. If creation is successful, the response contains the PresetToken which uniquely identifies the preset

    • ptz_RelativeMove($profileToken, $translationPantiltX, $translationPantiltY, $speedPantiltX, $speedPantiltY): this function supports relative Pan/Tilt movements (if PTZnode supports RelativeMove). The translation argument of this operation specifies the difference from the current position to the position to which the PTZ device is instructed to move
    • ptz_RelativeMoveZoom($profileToken, $zoom, $speedZoom): this function supports relative Zoom movement (if PTZnode supports RelativeMove)
    • ptz_AbsoluteMove($profileToken, $positionPantiltX,$positionPantiltY,$zoom): this function supports absolute Pan/Tilt or absolute Zoom movements (if PTZnode supports AbsoluteMove). The position argument of this command specifies the absolute position to which the PTZ unit moves
    • ptz_ContinuousMove($profileToken, $velocityPantiltX, $velocityPantiltY): this function supports continuous movements (on a PTZ-capable device). The velocity argument of this command specifies a signed speed value for the Pan, Tilt and Zoom
    • ptz_ContinuousMoveZoom($profileToken, $zoom): this function supports continuous movements (for a PTZ- capable device). The velocity argument of this command specifies a signed speed value for Zoom
    • ptz_Stop($profileToken, $pantilt, $zoom): this functions stops all ongoing pan, tilt and zoom movements (on a PTZ-capable device). The stop operation can be filtered to stop a specific movement by setting the corresponding stop argument

For details about ONVIF primitives (request parameters, response parameters, purpose of requests, etc.) I suggest you consult the official ONVIF documentation, in the section Resources I added some useful links. Enjoy!

Resources

This section contains links to software and documents that I recommend to look into. Some resources have been explicitly mentioned in the previous sections.


ONVIF Programming Revealed by Lorenzo Toscano is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

The software described here is a work in progress. It should be used with caution and new updates could continue to be added without any notice.

THE SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

You can influence the future of the how to lens by commenting in the guestbook. What do you like? What don't you like? What more would you like to see in ONVIF Programming Revealed?

Guestbook - This is the place to make your opinion known

    0 of 8192 characters used
    Post Comment

    • profile image

      antiplaka 3 years ago

      Hi ltoscano! Under which license ponvif is distributed? Wouldn't you mind posting your class to GitHub to enable collaboration?

      Mikhail.

    Click to Rate This Article