4

I'm implementing an application using ONVIF protocol. There is a WSDL file https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl which I have to work with. But it's necessary to define default service, to add following code into WSDL file:

<wsdl:service name="DeviceService">
    <wsdl:port name="DevicePort" binding="tds:DeviceBinding">
        <soap:address location="http://ip_address/onvif/device_service"/>
    </wsdl:port>
</wsdl:service>

But it's not possible due to these points:

  1. to add the Node into the WSDL file, you have to download the WSDL file (this is not a real problem, because I downloaded the file due to performance - for now)
  2. the application should communicate with many IP cameras in various networks, so it's not possible to define line: <soap:address location="http://ip/onvif/device_service"/>

So I was looking for some solution and I've found it in Zeep documentation (http://docs.python-zeep.org/en/master/client.html#creating-new-serviceproxy-objects), where is written:

There are situations where you either need to change the SOAP address from the one which is defined within the WSDL or the WSDL doesn’t define any service elements.

So I've tried to call this:

client = Client(
    wsdl = '/path/to/local/wsdl_file.wsdl',
    wsse = self.InitSecurity(),
    service_name = 'DeviceService',
    port_name = 'DevicePort'
)

service = client.create_service(
    '{http://www.onvif.org/ver10/device/wsdl}DeviceBinding',
    'http://ip_address/onvif/device_service'
)

But when I run the script, following exception is thrown:

ValueError: There is no default service defined. This is usually due to missing wsdl:service definitions in the WSDL

And when I modify WSDL file directly (add the Node above), everything works correctly.

Any idea, please? I'm fighting with a while, so I need to kick a little bit.

Thank you.

Honza
  • 939
  • 2
  • 11
  • 28

1 Answers1

2

The service = client.create_service() should work (see also https://github.com/mvantellingen/python-zeep/issues/106 for the same wsdl).

Are you using the created service object for subsequent calls (e.g. service.Operation() instead of the client?

mvantellingen
  • 1,229
  • 10
  • 6
  • Unfortunately, it doesn't work for me, but I wish :-(. After your answer I noticed my version of Zeep (0.21.0), and I thought it could be because of it. But according to release date it should contain working create_service() method. Nevertheless, I've updated to 1.1.0 but still not working - the same exception is thrown (no default service defined). And with "subsequent calls", I think I am - I'm calling client.service.Operation(), is it ok? Is the piece of code I wrote above correct (I mean code for client and create_service)? – Honza Feb 21 '17 at 06:37
  • No that's the reason it gives you the error actually. the client.service object is a default mapping. Since you create a new one with the create_service you need to use that instead. so my_service = client.create_service(..); my_service.operaton() – mvantellingen Feb 21 '17 at 07:36
  • 1
    So, your advice was the answer - but in combination with specific version of Zeep. It's little bit odd, but when I installed Zeep of versions from 0.21.0 to 0.24.0, it works perfectly, when I installed Zeep of versions 0.26.0 and 0.27.0, it works just one of X requests (in other X-1 requests it threw an exception I'll describe further) and when I installed Zeep of versions 1.0.0 and 1.1.0, there was everytime thrown an exception: "http.client.RemoteDisconnected: Remote end closed connection without response". So I've tried to upgrade each dependency, but it won't help. Thank you again. – Honza Feb 21 '17 at 08:55