ONVIF for Linux – Discovery

Completing the proxy generation

First I wanted to get rid of the errors “not implemented” and “deep recursion” that occurred during proxy generation.

I made local copies of all referenced XSDs and replaced references with xsd:anyType or commented out the attributes referencing http://docs.oasis-open.org/wsn/b-2 . This XSD had the most errors and was only referenced by the Event service which I would not use to begin with.

Next I had a problem with namespaces: wsdl2perl expects http://schemas.xmlsoap.org/wsdl/soap/ while ONVIF uses http://schemas.xmlsoap.org/wsdl/soap12/. Again I adjusted the ONVIF WSDLs.

Lastly I saw that the ONVIF WSDLs do not contain <service> elements. Which makes sense since every ip camera will have its own IP address. Nevertheless I needed at least one <service> and one <port> to successfully complete generation. So I added these elements with a bogus address to be replaced later on.

I then re-generated the proxy classes for the three WSDLs:

wsdl2perl.pl -p ONVIF::Device:: -b proxy file:wsdl/devicemgmt.wsdl
wsdl2perl.pl -p ONVIF::Media:: -b proxy file:wsdl/media.wsdl
wsdl2perl.pl -p ONVIF::PTZ:: -b proxy file:wsdl/ptz.wsdl

Aside: Since all three WSDLs reference onvif.xsd I now had all types from this file tripled – once in each service directory tree. A task for the future is to make a Common directory and factor out all classes generated from onvif.xsd.


I now had a nice  API but who should I call? What was the URL of those web services?

To solve this problem the ONVIF specification mandates that ONVIF devices support WS-Discovery. This is a UDP-multicast based protocol with semantics like this:

Client: “I need a device with attributes X. Who’s there?”
Device 1: “I am here and I can do X and Y”.
Device 2: “I am here and I can do only X”.
Device 3: [ keeps quiet, cannot do X.]

So I put together a small WSDL file with binding and service for WS-Discovery and generated a proxy for it using the techniques outlined above.

Additionally I implemented a SOAP-over-UDP transport module in Perl and a small test script:

require WSDiscovery::Interfaces::WSDiscovery::WSDiscoveryPort;
require WSDiscovery::Elements::Types;
require WSDiscovery::Elements::Scopes;
require WSDiscovery::TransportUDP;

sub discover
  my $svc_discover = WSDiscovery::Interfaces::WSDiscovery::WSDiscoveryPort->new();

  my $result = $svc_discover->ProbeOp(
    { # WSDiscovery::Types::ProbeType
      Types => { 'dn:NetworkVideoTransmitter', 'tds:Device' }, # QNameListType
      Scopes =>  { value => '' },
  die $result if not $result;
  print $result;


This test script got the following answer from my camera.

<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" xmlns:soapenc="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl" xmlns:tev="http://www.onvif.org/ver10/events/wsdl" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:tst="http://www.onvif.org/ver10/storage/wsdl" xmlns:ter="http://www.onvif.org/ver10/error" xmlns:dn="http://www.onvif.org/ver10/network/wsdl" xmlns:tns1="http://www.onvif.org/ver10/topics" xmlns:tmd="http://www.onvif.org/ver10/deviceIO/wsdl" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl" xmlns:wsoap12="http://schemas.xmlsoap.org/wsdl/soap12" xmlns:http="http://schemas.xmlsoap.org/wsdl/http" xmlns:d="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:wsadis="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrf-bf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wsntw="http://docs.oasis-open.org/wsn/bw-2" xmlns:wsrf-rw="http://docs.oasis-open.org/wsrf/rw-2" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:wsrf-r="http://docs.oasis-open.org/wsrf/r-2" xmlns:trc="http://www.onvif.org/ver10/recording/wsdl" xmlns:tse="http://www.onvif.org/ver10/search/wsdl" xmlns:trp="http://www.onvif.org/ver10/replay/wsdl" xmlns:tnsn="http://www.eventextension.com/2011/event/topics">
<d:AppSequence InstanceId="1404277082" MessageNumber="5"/>
<d:Types>dn:NetworkVideoTransmitter tds:Device</d:Types>

As you can see, the response neatly describes the device (TV-IP311PI), its capabilities (type/video_encoder, Profile/Streaming) and — most importantly — gives an address for the Device web service:

The next steps will be to call the web service at this address and query it for more capabilities. Also I want to integrate this into ZoneMinder.

I will keep you posted.

Tags: , , ,

One response to “ONVIF for Linux – Discovery”

  1. Vlăduţ Frăţiman says :

    Nice work! Congratulations!!!
    Keep waching your work. I’m interested in zoneminder integration!!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: