FalkTannhaeuser / python-onvif-zeep

ONVIF Client Implementation in Python 2+3 (using https://github.com/mvantellingen/python-zeep instead of suds as SOAP client)
MIT License
424 stars 138 forks source link

Unable to parse components in Onvif device GetCapabilities reply extension #57

Open peteratebs opened 4 years ago

peteratebs commented 4 years ago

Using commit aae3def4385b0f8922e0e83b9cdcd68b2263f739

The onvif device_service GetCapabilities reply has an extension section within it that zeep does not follow and parse and resolve into pythons objects attached to the result, which I think should be the behavior. The type in question, "CapabilitiesExtension", is declared in onvif.xsd, see below. I found through experimentation that by commenting out the line containing xs:any namespace="##other" in onvif.xsd II can see the objects properly. I've traced through the parsing code quite a bit and so far haven't found the problem.

The offending fragment in onvif.xsd

`  <xs:complexType name="CapabilitiesExtension">
      <xs:sequence>
<!-- Comment out this next kline and GetCababilities will work-->
           <xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
             <xs:element name="DeviceIO" type="tt:DeviceIOCapabilities" minOccurs="0"/>
              <xs:element name="Display" type="tt:DisplayCapabilities" minOccurs="0"/>

This code fragment below may be executed as a python script to show the problem. You must have access to an onvif camera with DeviceIO extensions, or edit the script if it supports another extension but not DeviceIO, and edit the login credentials and camera IP address to run it.

from zeep.client import Client, CachingClient, Settings
from zeep.proxy import ServiceProxy
from zeep.wsse.username import UsernameToken

def showbug():

    # Provide valid credentials for an Onvif camera that has at least one populate entry in DeviceCapabilities extension sectio
    # change to your userid, password, ip address
    user='user'
    passwd='password'
    IpAddress='172.32.12.33'
    Port = 80

    xaddr='http://{}:{}/onvif/device_service'.format(IpAddress,Port)

    wsse = UsernameToken(user, passwd, use_digest=True)
    settings = Settings()
    settings.strict = False
    settings.xml_huge_tree = True
    client = Client(wsdl='https://www.onvif.org/ver10/device/wsdl/devicemgmt.wsdl', wsse=wsse,transport=None,settings=settings)
    binding = client.wsdl.bindings['{http://www.onvif.org/ver10/device/wsdl}DeviceBinding']
    serviceproxy = ServiceProxy(client, binding, address=xaddr)

    capabilities = serviceproxy.GetCapabilities()
    if capabilities.Extension.DeviceIO == None:
        print ("GetCapabilities failed to parse extension")
        print ("Try removing line with from xs:any namespace=""##other"" from onvif.xsd line 2513 ")
    else:
        print ("GetCapabilities succeeded parsing extension")

if __name__ == '__main__':
    showbug()