Pycurl problem in the Dahua NVR and camera integration: debugging SaWey's component

Hello, I’m trying and trying to debug the SaWey custom component that permit to follow the Dahua’s cameras events. I found a few errors in his code and now it works all correctly when reading events, but the components has error in writing.

The original code is here: SaWey Github

The errors I found are:

URL_TEMPLATE = “{protocol}://{host}:{port}/cgi-bin/eventManager.cgi?action=attach&codes=%5B{events}%5D”

This is the correct URL_TEMPLATE to use according to the original Dahua API. In the SaWey url template there was an error.

CurlObj.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)

The digest authentication doesn’t work for me, correcting it to basic starts working.

Now reading the HA log I can see all the cameras events but a while after this, I have an error:

2018-04-08 13:57:28 DEBUG (Thread-24) [custom_components.dahua_event] [Dahua]: – myboundary
2018-04-08 13:57:28 DEBUG (Thread-24) [custom_components.dahua_event] [Dahua] OnDisconnect(Failed writing body (0 != 100) (23))

“–myboundary” is part of the url that it’s reading (that it need to ignore, but…).

I’m not a programmer and I’m not able to fix this problem. So I write here the part of the component that I think cause the error: I hope anyone could read it.

Here the Pycurl WRITEFUNCTION:

    device = DahuaDevice(self, hass, device_cfg.get("name"), url, channels_dict)
     self.Devices.append(device)

     CurlObj = pycurl.Curl()
     device.CurlObj = CurlObj

     CurlObj.setopt(pycurl.URL, url)
     CurlObj.setopt(pycurl.CONNECTTIMEOUT, 30)
     CurlObj.setopt(pycurl.TCP_KEEPALIVE, 1)
     CurlObj.setopt(pycurl.TCP_KEEPIDLE, 30)
     CurlObj.setopt(pycurl.TCP_KEEPINTVL, 15)
     CurlObj.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_BASIC)
     CurlObj.setopt(pycurl.USERPWD, "%s:%s" % (device_cfg.get("user"), device_cfg.get("password")))
     CurlObj.setopt(pycurl.WRITEFUNCTION, device.OnReceive)

OnReceive is where the component is searching the interesting part of the url content:

def OnReceive(self, data):
Data = data.decode(“utf-8”, errors=“ignore”)
_LOGGER.debug(“[{0}]: {1}”.format(self.Name, Data))

   for Line in Data.split("\r\n"):
       if Line == "HTTP/1.1 200 OK":
           self.OnConnect()

       if not Line.startswith("Code="):
           continue

       Alarm = dict()
       Alarm["name"] = self.Name
       for KeyValue in Line.split(';'):
           Key, Value = KeyValue.split('=')
           Alarm[Key] = Value

       if Alarm["index"] in self.Channels:
           Alarm["channel"] = self.Channels[Alarm["index"]]

       self.hass.bus.fire("dahua_event_received", Alarm)

The url content is like this one:

HTTP Code: 200 OK\r\n
Cache-Control: no-cache\r\n
Pragma: no-cache\r\n
Expires: Thu, 01 Dec 2099 16:00:00 GMT\r\n
Connection: close\r\n
Content-Type: multipart/x-mixed-replace; boundary=myboundary\r\n\r\n
Body:
–myboundary\r\n
Content-Type: text/plain\r\n
Content-Length: 39\r\n
Code=VideoMotion;action=Start;index=0\r\n\r\n

I don’t know why, but I think that the line starting with double dash is breaking the code. Why? How to solve it?
Thanks!

Hi eporedieis,

Did you ever find a solution to this or get any assistance from @SaWey?

I was wanting to use his component on a Hass.io installation, but cannot due to the pycurl dependency.

If only the code could be updated to use Python’s “requests” function instead of pycurl, then it should work on any HA install without any dependencies - and be a lot easier to debug to solve the issue you found. From the Python docs, it’s clear the requests function has a far simpler API than pycurl. See: https://github.com/yudazilian/Pycurl-vs-Requests

Only problem for me is that I have never programmed in Python before, but I’ll try to see if I can figure something out.