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

Error with GetSreamUri Function: No namespace defined for 'ter' #27

Open uched41 opened 5 years ago

uched41 commented 5 years ago

Hello Guys I get this error when I try to run the function GetStreamUri:

  File "/usr/local/lib/python3.5/dist-packages/onvif_zeep-0.2.12-py3.5.egg/onvif/client.py", line 23, in wrapped
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.5/dist-packages/onvif_zeep-0.2.12-py3.5.egg/onvif/client.py", line 153, in wrapped
    return call(params, callback)
  File "/usr/local/lib/python3.5/dist-packages/onvif_zeep-0.2.12-py3.5.egg/onvif/client.py", line 140, in call
    ret = func(**params)
  File "/usr/local/lib/python3.5/dist-packages/zeep-3.1.0-py3.5.egg/zeep/proxy.py", line 42, in __call__
    self._op_name, args, kwargs)
  File "/usr/local/lib/python3.5/dist-packages/zeep-3.1.0-py3.5.egg/zeep/wsdl/bindings/soap.py", line 132, in send
    return self.process_reply(client, operation_obj, response)
  File "/usr/local/lib/python3.5/dist-packages/zeep-3.1.0-py3.5.egg/zeep/wsdl/bindings/soap.py", line 194, in process_reply
    return self.process_error(doc, operation)
  File "/usr/local/lib/python3.5/dist-packages/zeep-3.1.0-py3.5.egg/zeep/wsdl/bindings/soap.py", line 338, in process_error
    subcode_qname = as_qname(subcode_value_element.text, subcode_value_element.nsmap, None)
  File "/usr/local/lib/python3.5/dist-packages/zeep-3.1.0-py3.5.egg/zeep/utils.py", line 31, in as_qname
    "No namespace defined for %r (%r)" % (prefix, value))
zeep.exceptions.XMLParseError: No namespace defined for 'ter' ('ter:InvalidArgVal')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "testcam.py", line 32, in <module>
    print(media_service.GetStreamUri(obj))
  File "/usr/local/lib/python3.5/dist-packages/onvif_zeep-0.2.12-py3.5.egg/onvif/client.py", line 26, in wrapped
    raise ONVIFError(err)
onvif.exceptions.ONVIFError: Unknown error: No namespace defined for 'ter' ('ter:InvalidArgVal')

Here is the funtion I am running:

from onvif import ONVIFCamera, ONVIFService

 mycam = ONVIFCamera('192.168.0.112', 80, 'admin', '12345')
 media_service = mycam.create_media_service()
 profiles = media_service.GetProfiles()
 token = profiles[0].token         // using attribute '_token' returns and error so I am using atribute 'token'

obj = media_service.create_type('GetStreamUri')
obj.ProfileToken = token
obj.StreamSetup = {'Stream': 'RTP-Unicast', 'Transport': {'Protocol': 'RTSP'}}
print(media_service.GetStreamUri(obj))

The error occurs on the funtion:

obj = media_service.create_type('GetStreamUri')

I have tried installing using pip3 and I have also tried installing from the github repo. I have also checkout different versions of the github repo, but all give the same error.

Any help will be appreciated, thanks, @FalkTannhaeuser @sinchb @iomihai @mpromonet @eLvErDe

uched41 commented 5 years ago

I was able to narrow the issue down by using wireshark to observe the requests being sent. There seems to be an error in the request:

This is the result when I sniff packets from the script,

POST /onvif/media_service HTTP/1.1
Host: 192.168.0.10
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: Zeep/2.0.0 (www.python-zeep.org)
Connection: keep-alive
SOAPAction: "http://www.onvif.org/ver10/media/wsdl/GetStreamUri"
Content-Type: application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver10/media/wsdl/GetStreamUri"
Content-Length: 1384

<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="http://www.w3.org/2003/05/soap-envelope">
  <soap-env:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <wsse:UsernameToken>
        <wsse:Username>admin</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">sl4l/u7/drfe9PawwI6bWO6m+Ew=</wsse:Password>
        <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">zwmmWqZjGYxuDDCaZhRSGA==</wsse:Nonce>
        <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2018-10-12T04:06:01+00:00</wsu:Created>
      </wsse:UsernameToken>
    </wsse:Security>
  </soap-env:Header>
  <soap-env:Body>
    <ns0:GetStreamUri xmlns:ns0="http://www.onvif.org/ver10/media/wsdl">
      <ns0:StreamSetup>
        <ns1:Stream xmlns:ns1="http://www.onvif.org/ver10/schema">RTP-Unicast</ns1:Stream>
        <ns2:Transport xmlns:ns2="http://www.onvif.org/ver10/schema">
          <ns2:Protocol>RTSP</ns2:Protocol>
        </ns2:Transport>
      </ns0:StreamSetup>
      <ns0:ProfileToken>MainStreamTooken</ns0:ProfileToken>
    </ns0:GetStreamUri>
  </soap-env:Body>
</soap-env:Envelope>

HTTP/1.1 400 Bad Request
Server: gSOAP/2.8
Content-Type: application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver10/media/wsdl/GetStreamUri"
Content-length: 2010
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsdd="http://schemas.xmlsoap.org/ws/2005/04/discovery" xmlns:chan="http://schemas.microsoft.com/ws/2005/02/duplex" xmlns:wsa5="http://www.w3.org/2005/08/addressing" xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:wsc="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:xmime="http://tempuri.org/xmime.xsd" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:tt="http://www.onvif.org/ver10/schema" xmlns:wsrfbf="http://docs.oasis-open.org/wsrf/bf-2" xmlns:wstop="http://docs.oasis-open.org/wsn/t-1" xmlns:wsrfr="http://docs.oasis-open.org/wsrf/r-2" xmlns:tdn="http://www.onvif.org/ver10/network/wsdl" xmlns:tds="http://www.onvif.org/ver10/device/wsdl" xmlns:tdv="http://www.onvif.org/ver10/events/wsdl" xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2" xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl" xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl" xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl"><SOAP-ENV:Body><SOAP-ENV:Fault><SOAP-ENV:Code><SOAP-ENV:Value>SOAP-ENV:Receiver</SOAP-ENV:Value><SOAP-ENV:Subcode><SOAP-ENV:Value>ter:InvalidArgVal</SOAP-ENV:Value><SOAP-ENV:Subcode><SOAP-ENV:Value>ter:NoConfig</SOAP-ENV:Value></SOAP-ENV:Subcode></SOAP-ENV:Subcode></SOAP-ENV:Code><SOAP-ENV:Reason><SOAP-ENV:Text xml:lang="en"></SOAP-ENV:Reason></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope>

Compared to the results when I sniff packets of the same request coming from ONViFManager:

POST /onvif/media_service HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver10/media/wsdl/GetStreamUri"
Host: 192.168.0.10
Content-Length: 498
Accept-Encoding: gzip, deflate
Connection: Close

<s:Envelope
    xmlns:s="http://www.w3.org/2003/05/soap-envelope">
    <s:Body
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <GetStreamUri
            xmlns="http://www.onvif.org/ver10/media/wsdl">
            <StreamSetup>
                <Stream
                    xmlns="http://www.onvif.org/ver10/schema">RTP-Unicast
                </Stream>
                <Transport
                    xmlns="http://www.onvif.org/ver10/schema">
                    <Protocol>RTSP</Protocol>
                </Transport>
            </StreamSetup>
            <ProfileToken>MainStreamTooken</ProfileToken>
        </GetStreamUri>
    </s:Body>
</s:Envelope>HTTP/1.1 200 OK
Server: gSOAP/2.8
Content-Type: application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver10/media/wsdl/GetStreamUri"
Content-length: 1931
Connection: close

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
    xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
    xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
    xmlns:wsdd="http://schemas.xmlsoap.org/ws/2005/04/discovery"
    xmlns:chan="http://schemas.microsoft.com/ws/2005/02/duplex"
    xmlns:wsa5="http://www.w3.org/2005/08/addressing"
    xmlns:c14n="http://www.w3.org/2001/10/xml-exc-c14n#"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
    xmlns:wsc="http://docs.oasis-open.org/ws-sx/ws-secureconversation/200512"
    xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    xmlns:xmime="http://tempuri.org/xmime.xsd"
    xmlns:xop="http://www.w3.org/2004/08/xop/include"
    xmlns:tt="http://www.onvif.org/ver10/schema"
    xmlns:wsrfbf="http://docs.oasis-open.org/wsrf/bf-2"
    xmlns:wstop="http://docs.oasis-open.org/wsn/t-1"
    xmlns:wsrfr="http://docs.oasis-open.org/wsrf/r-2"
    xmlns:tdn="http://www.onvif.org/ver10/network/wsdl"
    xmlns:tds="http://www.onvif.org/ver10/device/wsdl"
    xmlns:tdv="http://www.onvif.org/ver10/events/wsdl"
    xmlns:wsnt="http://docs.oasis-open.org/wsn/b-2"
    xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl"
    xmlns:trt="http://www.onvif.org/ver10/media/wsdl"
    xmlns:tan="http://www.onvif.org/ver20/analytics/wsdl"
    xmlns:timg="http://www.onvif.org/ver20/imaging/wsdl">
    <SOAP-ENV:Body>
        <trt:GetStreamUriResponse>
            <trt:MediaUri>
                <tt:Uri>rtsp://192.168.0.10:554/ch0_0.h264</tt:Uri>
                <tt:InvalidAfterConnect>false</tt:InvalidAfterConnect>
                <tt:InvalidAfterReboot>false</tt:InvalidAfterReboot>
                <tt:Timeout>PT0S</tt:Timeout>
            </trt:MediaUri>
        </trt:GetStreamUriResponse>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

It looks like there is an error in XML formatting.

mpromonet commented 5 years ago

Hi uched41, In the script case, there is the soap header with wsse information that are not present with onvifdm. Did you try to post the request using curlor whatever to identify what is the part that allow the sever to understand the request ? Best Regards, Michel.

uched41 commented 5 years ago

Hello mpromonet, I have inspected both requests and curl will work. I have tried using curl, and it works. The difference it the ns0 and ns1 in the request, Is there any way I can remove them

<ns0:GetStreamUri xmlns:ns0="http://www.onvif.org/ver10/media/wsdl">
      <ns0:StreamSetup>
        <ns1:Stream xmlns:ns1="http://www.onvif.org/ver10/schema">RTP-Unicast</ns1:Stream>
        <ns2:Transport xmlns:ns2="http://www.onvif.org/ver10/schema">
          <ns2:Protocol>RTSP</ns2:Protocol>
        </ns2:Transport>
      </ns0:StreamSetup>
      <ns0:ProfileToken>MainStreamTooken</ns0:ProfileToken>
    </ns0:GetStreamUri>
mpromonet commented 5 years ago

Hi uched41, Obvisously this depends on the parser of your server, but <ns0:GetStreamUri xmlns:ns0="http://www.onvif.org/ver10/media/wsdl"> should be equivalent to <GetStreamUri xmlns="http://www.onvif.org/ver10/media/wsdl"> Best Regards, Michel.

hubugui commented 5 years ago

I write a simple base on example/streaming.py and python-onvif-zeep/issues/4, it work nice with HiKvision camera, as follow:

import zeep
from onvif import ONVIFCamera, ONVIFService

def zeep_pythonvalue(self, xmlvalue):
    return xmlvalue

zeep.xsd.simple.AnySimpleType.pythonvalue = zeep_pythonvalue

def media_profile_configuration():
    '''
    A media profile consists of configuration entities such as video/audio
    source configuration, video/audio encoder configuration,
    or PTZ configuration. This use case describes how to change one
    configuration entity which has been already added to the media profile.
    '''

    # Create the media service
    mycam = ONVIFCamera('192.168.5.248', 80, 'admin', 'xxxxxx', 'E://python-onvif-zeep/wsdl/')
    media_service = mycam.create_media_service()

    token = None
    profiles = media_service.GetProfiles()
    print("dump profiles and find first profile token")
    for prof in profiles:
        if not token:
            token = prof["token"]
            print(token)

    # Use the first profile and Profiles have at least one
    # token = profiles[0]._token
    token = "Profile_1"

    # Get all video encoder configurations
    configurations_list = media_service.GetVideoEncoderConfigurations()
    print("dump configuration list")
    for config in configurations_list:
        print(config)

    obj = media_service.create_type('GetStreamUri')
    obj.ProfileToken = token
    obj.StreamSetup = {'Stream': 'RTP-Unicast', 'Transport': {'Protocol': 'RTSP'}}
    print("dump stream uri")
    print(media_service.GetStreamUri(obj))

if __name__ == '__main__':
    media_profile_configuration()
ashish1405 commented 3 years ago

I know this is old, but if anyone faces this issue, try to replace the code in client.py - ONVIFService - __init__ From

       self.create_type = lambda x: self.zeep_client.get_element('ns0:' + x)()

to

        namespace = binding_name[binding_name.find("{") + 1 : binding_name.find("}")]
        available_ns = self.zeep_client.namespaces
        active_ns = (
            list(available_ns.keys())[list(available_ns.values()).index(namespace)]
            or "ns0"
        )
        self.create_type = lambda x: self.zeep_client.get_element(active_ns + ":" + x)()