python-onvif-zeep
python-onvif-zeep copied to clipboard
onvif.exceptions.ONVIFError: Unknown error: ('Connection aborted.', BadStatusLine('POST... *HTTP/1.1 500 Internal Server Error\r\n'))
Hi, I was trying to connect TP-Link tapo C220 ip camera with python, but I 'm stuck on a problem. Here is my code :
import time
from onvif import ONVIFCamera
import zeep
import requests
from requests.auth import HTTPDigestAuth
wsdl_path = r'C:/Users/user/Desktop/python-onvif/python-onvif-zeep/wsdl'
camera_ip = '192.168.X.XXX'
username = 'user'
password = '123456'
def zeep_pythonvalue(self, xmlvalue):
return xmlvalue
def absolute_move():
pan = 0
pan_speed = 1
tilt = 0
tilt_speed = 1
mycam = ONVIFCamera(camera_ip, 80, username, password, wsdl_path)
# Create media service object
media = mycam.create_media_service()
# Create ptz service object
ptz = mycam.create_ptz_service()
# Get target profile
zeep.xsd.simple.AnySimpleType.pythonvalue = zeep_pythonvalue
media_profile = media.GetProfiles()[0]
request = ptz.create_type('AbsoluteMove')
request.ProfileToken = media_profile.token
ptz.Stop({'ProfileToken': media_profile.token})
if request.Position is None:
request.Position = ptz.GetStatus({'ProfileToken': media_profile.token}).Position
if request.Speed is None:
request.Speed = ptz.GetStatus({'ProfileToken': media_profile.token}).Position
request.Position.PanTilt.x = pan
request.Speed.PanTilt.x = pan_speed
request.Position.PanTilt.y = tilt
request.Speed.PanTilt.y = tilt_speed
ptz.AbsoluteMove(request)
print('finish')
def snap():
# Get target profile
zeep.xsd.simple.AnySimpleType.pythonvalue = zeep_pythonvalue
mycam = ONVIFCamera(camera_ip, 80, username, password, wsdl_path)
media = mycam.create_media_service()
media_profile = media.GetProfiles()[0]
res = media.GetSnapshotUri({'ProfileToken': media_profile.token})
response = requests.get(res.Uri, auth=HTTPDigestAuth("admin", "pass"))
res = "{_time}.png".format(_time=time.strftime('%Y_%m_%d_%H_%M_%S', time.localtime(time.time())))
with open(res, 'wb') as f:
f.write(response.content)
def gotoPreset():
zeep.xsd.simple.AnySimpleType.pythonvalue = zeep_pythonvalue
mycam = ONVIFCamera(camera_ip, 80, username, password, wsdl_path)
media = mycam.create_media_service()
ptz = mycam.create_ptz_service()
params = ptz.create_type('GotoPreset')
media_profile = media.GetProfiles()[0]
print(media_profile.token)
params.ProfileToken = media_profile.token
params.PresetToken = 1
re = ptz.GotoPreset(params)
print(re)
def getStatus():
zeep.xsd.simple.AnySimpleType.pythonvalue = zeep_pythonvalue
mycam = ONVIFCamera(camera_ip, 80, username, password, wsdl_path)
media = mycam.create_media_service()
ptz = mycam.create_ptz_service()
params = ptz.create_type('GetStatus')
media_profile = media.GetProfiles()[0]
print(media_profile.token)
params.ProfileToken = media_profile.token
res = ptz.GetStatus(params)
print(res)
if __name__ == '__main__':
absolute_move()
snap()
gotoPreset()
getStatus()
When I start this code, it is the error message:
Traceback (most recent call last): File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\urllib3\connectionpool.py", line 790, in urlopen response = self._make_request( ^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\urllib3\connectionpool.py", line 536, in _make_request response = conn.getresponse() ^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\urllib3\connection.py", line 461, in getresponse httplib_response = super().getresponse() ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 1378, in getresponse response.begin() File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 318, in begin version, status, reason = self._read_status() ^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 300, in _read_status raise BadStatusLine(line) http.client.BadStatusLine: POST /onvif/serviceHTTP/1.1Host 192.168.1.xxx:xxxUser-Agent Zeep/4.2.1 (www.python-zeep.org)Accept-Encoding gzip, deflateAccept *HTTP/1.1 500 Internal Server Error During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\adapters.py", line 486, in send resp = conn.urlopen( ^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\urllib3\connectionpool.py", line 844, in urlopen retries = retries.increment( ^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\urllib3\util\retry.py", line 470, in increment raise reraise(type(error), error, _stacktrace) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\urllib3\util\util.py", line 38, in reraise raise value.with_traceback(tb) File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\urllib3\connectionpool.py", line 790, in urlopen response = self._make_request( ^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\urllib3\connectionpool.py", line 536, in _make_request response = conn.getresponse() ^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\urllib3\connection.py", line 461, in getresponse httplib_response = super().getresponse() ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 1378, in getresponse response.begin() File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 318, in begin version, status, reason = self._read_status() ^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\http\client.py", line 300, in _read_status raise BadStatusLine(line) urllib3.exceptions.ProtocolError: ('Connection aborted.', BadStatusLine('POST /onvif/service\x00HTTP/1.1\x00\x00Host\x00 192.168.1.xxx:xxx\x00\x00User-Agent\x00 Zeep/4.2.1 (www.python-zeep.org)\x00\x00Accept-Encoding\x00 gzip, deflate\x00\x00Accept\x00 *HTTP/1.1 500 Internal Server Error\r\n')) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\onvif_zeep-0.2.12-py3.11.egg\onvif\client.py", line 25, in wrapped return func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\onvif_zeep-0.2.12-py3.11.egg\onvif\client.py", line 150, in wrapped return call(params, callback) ^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\onvif_zeep-0.2.12-py3.11.egg\onvif\client.py", line 138, in call ret = func(**params) ^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\zeep-4.2.1-py3.11.egg\zeep\proxy.py", line 46, in call return self._proxy._binding.send( ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\zeep-4.2.1-py3.11.egg\zeep\wsdl\bindings\soap.py", line 127, in send response = client.transport.post_xml(options["address"], envelope, http_headers) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\zeep-4.2.1-py3.11.egg\zeep\transports.py", line 108, in post_xml return self.post(address, message, headers) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\zeep-4.2.1-py3.11.egg\zeep\transports.py", line 74, in post response = self.session.post( ^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\sessions.py", line 637, in post return self.request("POST", url, data=data, json=json, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\sessions.py", line 589, in request resp = self.send(prep, **send_kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\sessions.py", line 703, in send r = adapter.send(request, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\requests\adapters.py", line 501, in send raise ConnectionError(err, request=request) requests.exceptions.ConnectionError: ('Connection aborted.', BadStatusLine('POST /onvif/service\x00HTTP/1.1\x00\x00Host\x00 192.168.1.xxx:xxx\x00\x00User-Agent\x00 Zeep/4.2.1 (www.python-zeep.org)\x00\x00Accept-Encoding\x00 gzip, deflate\x00\x00Accept\x00 *HTTP/1.1 500 Internal Server Error\r\n')) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "c:\Users\user\Desktop\vision\vision\onvif_control.py", line 102, in
absolute_move() File "c:\Users\user\Desktop\vision\vision\onvif_control.py", line 44, in absolute_move request.Position = ptz.GetStatus({'ProfileToken': media_profile.token}).Position ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Users\user\AppData\Local\Programs\Python\Python311\Lib\site-packages\onvif_zeep-0.2.12-py3.11.egg\onvif\client.py", line 27, in wrapped raise ONVIFError(err) onvif.exceptions.ONVIFError: Unknown error: ('Connection aborted.', BadStatusLine('POST /onvif/service\x00HTTP/1.1\x00\x00Host\x00 192.168.1.xxx:xxx\x00\x00User-Agent\x00 Zeep/4.2.1 (www.python-zeep.org)\x00\x00Accept-Encoding\x00 gzip, deflate\x00\x00Accept\x00 *HTTP/1.1 500 Internal Server Error\r\n'))`
What's wrong with my code? Thanks
I have a similar problem with a Tapo 500. Basically, nothing works so I captured the traffic and I figured out that the Tapo does not like the GetCapabilities request.
request.xml:
<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>
xxxxxxxxx
</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
xxxxxxxxxxx
</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soap-env:Header>
<soap-env:Body>
<ns0:GetCapabilities xmlns:ns0="http://www.onvif.org/ver10/device/wsdl"/>
</soap-env:Body>
</soap-env:Envelope>
When I use curl to do the POST request, it returns an error. I believe that there was not even a reply. The connection is simply closed.
# curl -k -X POST --header 'Content-Type: text/xml; charset=utf-8' -d @request.xml "http://192.168.1.26:2020/onvif/device_service"
curl: (1) Received HTTP/0.9 when not allowed
-:1: parser error : Document is empty
I eventually found what seems to be the problem: The Tapo does not like the self-closing tag <ns0:GetCapabilities ... />.
For example, the following GetCapabilities request works fine
<?xml version=1.0' encoding='utf-8'>
<soap-env:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<soap-env:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetCapabilities xmlns="http://www.onvif.org/ver10/device/wsdl"></GetCapabilities>
</soap-env:Body>
</soap-env:Envelope>
but that one does not
<?xml version=1.0' encoding='utf-8'>
<soap-env:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<soap-env:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GetCapabilities xmlns="http://www.onvif.org/ver10/device/wsdl"/>
</soap-env:Body>
</soap-env:Envelope>
This is quite a problem because there are probably a lot of onvif clients that do not work on the tapo for the same reason.
I will try to fill a ticket at Tp-Link about.
Is there a way to prevent onvif-zeep to produce closing tags?
I figured out how to prevent self-closing tags. The XML is produced in package zeep by the function etree_to_string in wsdl/utils.py
The trick is to insert an empty text in all empty elements so
def etree_to_string(node):
for elem in node.iter():
if elem.text == None:
elem.text = ''
return etree.tostring(
node, pretty_print=False, xml_declaration=True, encoding="utf-8"
)
So I can now successfully do the GetCapabilities and a few other requests.
I still get a disconnection later in my test script but this is probably because I am trying to use an feature that is not supported by my Tapo 500 (i.e. PTZ ContinuousMove)
I noticed some self-closing tag in a network trace from another onvif tool that appears to be working fine so my initial diagnostic is probably incorrect. Something odd is happening here!!!