Hikvision event stream sensors

I wrote the post below about how I setup a nodejs script to update sensors in HA.

I have started to look at turning this into a compnent. I experimented using pycurl but ended up blocking HA. I have not played around with asyncio or aiohttp yet and am not sure how to put that together.

What I am looking for here is some guidance on how to create a component that will monitor the Hikvision http stream and update the appropriate sensors.

The stream from the Hikvision is a multipart http stream containing XML. I figure there must be a way to use aiohttp to watch this and feed the info to the sensors but that is beyond my coding skills at the moment.

Check out the openhab nodejs hikvision event script here:

I’ve been working on this off and on for the past month or so. I have the event stream handling portion more or less done and have been working on the hass side of things more recently. Look for a PR in a week or so hopefully.

1 Like

Awesome. If you need any help with testing or tackling some of the coding issues let me know.

Will do. Once I get things more functional i’ll send you a PM to test before I submit a PR. It always helps to have more people looking for issues.

From my use of the nodejs script and module so far I have made the following observations that I think need to be included in a HA component.

  • no error checking in the script. I tried to implement it using the error checking the module but i didn’t get it working. Some error logging for things such as user privileges etc should be implemented.
  • the timeout for an event is hard coded to be 2 seconds if it is not detected again. At the sensor level I think there needs to be a customisable timeout to prevent multiple events in a short time. For instance setting a 60s timeout for line crossing to stop repeat firing for multiple line crosses in a short time.
  • the nodejs module doesn’t have the codes for intrusion detection built in, I think that it is “fielddetection” (I am not near my HA server so cannot check). There maybe other codes that need to be added. I think the best way to approach this is to give friendly names for codes recognised and leave the others untouched so that they can still be specified.

I envision the YAML config entry to look something like:

sensor:
- name: "hik_cam1"
  platform: hikvision_events
  host: "192.168.0.1"
  port: 80                               (Optional)
  username: "username"
  password: "password"
  timeout: 60                            (Optional)
  events:
    - AlarmLocal
    - VideoMotion
    - LineDetection
    - VideoLoss
    - VideoBlind

I typed this on my mobile so sorry for any formatting issues.

Edit: fixed the sensor config to use yaml and added missing lines

The implementation I currently have in testing works like so:

  • Lots of error catching. This is one of the main things that’s been making testing so tricky. I’m trying to work out a lot of the issues organically by letting the library run for a couple days of normal usage and handling what comes up.
  • I found a 5 second delay to work best for events. It’s hardcoded at the moment, but would be simple to breakout if you think it’s beneficial.
  • I autodiscover the event types by looking for those that have “Notify Surveillance Center” checked under the event linkage setup in the camera. This gives the library some flexibility for use inside and outside of HASS since a user can configure what they want through the friendly camera interface rather than a text file.

I’m getting close to being happy with it where it is and will push everything from my local repositories to github soon.

1 Like

You’re a few steps ahead of me.

I think there should be two timeout setting in the component. Timeout might not be the best terminology, but I will stick with it for this post.

  1. For monitoring the event stream, the timeout setting of hard coded 5 seconds is fine. Many of the events send an inactive status anyway, so it may not get used much in that way.

  2. For the sensor presented to HA an optional timeout that keeps the sensor active once the event stream status is inactive.
    I have considered this after using my cameras and getting multiple event notifications for a single physical event.
    Some examples.

  • Bidirectional line detection at the front of a house. A person walks to mailbox crossing the line and walking back 10 seconds later will trip as two events.
  • Motion detection for a zone sensitive enough to detect a person. A person enters the zone, tripping the motion. The person stops inside the detection zone for 10s (checks phone glued to hand), motion detection event stops. The person continues walking out of zone, triggers event again.

Many PIR sensors use a similar timeout system to prevent multiple system events for a single physical event.

Edit: spelling and grammar.

You’ve convinced me a configurable off-delay is a good idea. I’ll work it into the component.

I’ve finally gotten everything to a stable point where I think it would be beneficial to have someone else test.

The code you need is in two repositories:

For testing you can install the library locally by downloading the repository then pointing pip to it like this:

pip install -e /path/to/repo

The component will automatically add all sensors that are configured to notify the surveillance center (in the camera gui) and is configured like this:

binary_sensor:
  - platform: hikvision
    host: 192.168.15.5
    port: 80
    ssl: False
    username: user
    password: pass
    customize:
      binary_sensor.sensor_name_1:
        delay: 30
      binary_sensor.sensor_name_2:
        ignored: True

The port, ssl, and customize parameters are optional. Each sensor listed in customize can have delay and ignored options, with delay being the number of seconds to delay the state update after it’s reported off and the ignored option is another way to tell HASS to not add the sensor.

I’m interested to see how well things work for you. Any feedback is appreciated.

1 Like

I am away for the next day or two but will test it out when I have a chance.

1 Like

@mezz64
I tried setting up the custom component today and got the following error in my log:

16-12-05 09:09:09 homeassistant.loader: Loaded binary_sensor.hikvision from custom_components.binary_sensor.hikvision
16-12-05 09:09:09 homeassistant.bootstrap: Setting up binary_sensor
16-12-05 09:09:09 homeassistant.components.binary_sensor: Setting up binary_sensor.hikvision
16-12-05 09:09:10 homeassistant.components.binary_sensor: Error while setting up platform hikvision
Traceback (most recent call last):
  File "/usr/src/app/homeassistant/helpers/entity_component.py", line 150, in _async_setup_platform
    entity_platform.add_entities, discovery_info
  File "uvloop/future.pyx", line 230, in __iter__ (uvloop/loop.c:103621)
  File "uvloop/future.pyx", line 432, in uvloop.loop.BaseTask._fast_wakeup (uvloop/loop.c:106780)
  File "uvloop/future.pyx", line 101, in uvloop.loop.BaseFuture._result_impl (uvloop/loop.c:102039)
  File "/usr/local/lib/python3.5/concurrent/futures/thread.py", line 55, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/binary_sensor/hikvision.py", line 80, in setup_platform
    data = HikvisionData(hass, url, port, name, username, password)
  File "/config/custom_components/binary_sensor/hikvision.py", line 119, in __init__
    self._username, self._password)
  File "/usr/local/lib/python3.5/site-packages/pyhik/hikvision.py", line 95, in __init__
    self.initialize()
  File "/usr/local/lib/python3.5/site-packages/pyhik/hikvision.py", line 132, in initialize
    False, 1, 0, datetime.datetime.now()]
KeyError: 'PIR'

I haven’t spent any time trying to figure out the problem yet.

Looks like your camera model has a sensor type that mine don’t named PIR. Can you let me know what event types you have checked to “Notify Surveillance Center” in your camera configuration?

In any case, you already identified a spot in the library that should be wrapped in a catch block so thanks for testing this out.

I’ve updated the pyHik library to allow adding any event sensors it finds, not just those that I have defined friendly names for. This should correct your error.

Please update the pyHik files and try again.

I am testing with a DS-2CD2032-I.

It has events for:

  • motion detection (enabled)
  • video tampering
  • exception
  • line crossing detection (enabled)
  • intrusion detection (enabled)

I am not sure what the PIR event is as I haven’t seen that in any of my testing.

I will update pyHik and see how it goes.

1 Like

Everything seems to be working well with the latest changes.

No sign of the PIR event the caused the initial error though.

Glad to hear it’s working. It’s odd the PIR event didn’t show up again though. Could you post the XML you get when you visit this URL: http://Your-Cam-IP/ISAPI/Event/triggers

I parse through that XML tree to generate the event dictionary so there may be more info in there about the PIR event.

I will get the xml to you soon. I didn’t see any PIR events when I monitored it with nodejs though or when looking at the event stream with curl.

I have just noticed though that the HA sensors are not actually changing when motion is detected. I will investigate to see what’s going on.

Be sure to enable debug logging for the hikvsion component so you can see whats going on in the logs.

    pyhik.hikvision: debug
    homeassistant.components.binary_sensor.hikvision: debug

@mezz64 I’m also interested in importing motion detection from HIK as HAAS sensor. Here is the requested XML from my camera (DS-2CD2142FWD-I)

<?xml version="1.0" encoding="UTF-8"?>
<EventNotification version="2.0" xmlns="http://www.hikvision.com/ver20/XMLSchema">
<EventTriggerList version="2.0" xmlns="http://www.hikvision.com/ver20/XMLSchema">
<EventTrigger>
<id>VMD-1</id>
<eventType>VMD</eventType>
<eventDescription>VMD Event trigger Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
<EventTriggerNotification>
<id>record-1</id>
<notificationMethod>record</notificationMethod>
<videoInputID>1</videoInputID>
<notificationRecurrence>beginning</notificationRecurrence>
</EventTriggerNotification>
<EventTriggerNotification>
<id>beep</id>
<notificationMethod>beep</notificationMethod>
<notificationRecurrence>beginning</notificationRecurrence>
</EventTriggerNotification>
<EventTriggerNotification>
<id>center</id>
<notificationMethod>center</notificationMethod>
<notificationRecurrence>beginning</notificationRecurrence>
</EventTriggerNotification>
<EventTriggerNotification>
<id>FTP</id>
<notificationMethod>FTP</notificationMethod>
<notificationRecurrence>beginning</notificationRecurrence>
</EventTriggerNotification>
</EventTriggerNotificationList>
</EventTrigger>
<EventTrigger>
<id>tamper-1</id>
<eventType>tamperdetection</eventType>
<eventDescription>shelteralarm Event trigger Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
</EventTriggerNotificationList>
</EventTrigger>
<EventTrigger>
<id>diskfull</id>
<eventType>diskfull</eventType>
<eventDescription>exception Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
</EventTriggerNotificationList>
</EventTrigger>
<EventTrigger>
<id>diskerror</id>
<eventType>diskerror</eventType>
<eventDescription>exception Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
<EventTriggerNotification>
<id>beep</id>
<notificationMethod>beep</notificationMethod>
<notificationRecurrence>beginning</notificationRecurrence>
</EventTriggerNotification>
</EventTriggerNotificationList>
</EventTrigger>
<EventTrigger>
<id>nicbroken</id>
<eventType>nicbroken</eventType>
<eventDescription>exception Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
</EventTriggerNotificationList>
</EventTrigger>
<EventTrigger>
<id>ipconflict</id>
<eventType>ipconflict</eventType>
<eventDescription>exception Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
</EventTriggerNotificationList>
</EventTrigger>
<EventTrigger>
<id>illaccess</id>
<eventType>illaccess</eventType>
<eventDescription>exception Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
</EventTriggerNotificationList>
</EventTrigger>
<EventTrigger>
<id>linedetection-1</id>
<eventType>linedetection</eventType>
<eventDescription>Linedetection Event trigger Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
</EventTriggerNotificationList>
</EventTrigger>
<EventTrigger>
<id>fielddetection-1</id>
<eventType>fielddetection</eventType>
<eventDescription>fielddetection Event trigger Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
</EventTriggerNotificationList>
</EventTrigger>
<EventTrigger>
<id>videomismatch</id>
<eventType>videomismatch</eventType>
<eventDescription>exception Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
<EventTriggerNotification>
<id>beep</id>
<notificationMethod>beep</notificationMethod>
<notificationRecurrence>beginning</notificationRecurrence>
</EventTriggerNotification>
</EventTriggerNotificationList>
</EventTrigger>
<EventTrigger>
<id>badvideo</id>
<eventType>badvideo</eventType>
<eventDescription>exception Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
</EventTriggerNotificationList>
</EventTrigger>
<EventTrigger>
<id>storageDetection-1</id>
<eventType>storageDetection</eventType>
<eventDescription>storageDetection Event trigger Information</eventDescription>
<videoInputChannelID>1</videoInputChannelID>
<dynVideoInputChannelID>1</dynVideoInputChannelID>
<EventTriggerNotificationList>
</EventTriggerNotificationList>
</EventTrigger>
</EventTriggerList>
</EventNotification>

I’m trying to give it a try, but hitting a wall. I’ve installed pyhik locally in the HA’s docker container:

# pip install git+git://github.com/mezz64/pyHik
Collecting git+git://github.com/mezz64/pyhik
  Cloning git://github.com/mezz64/pyhik to /tmp/pip-qcxptk1o-build
Installing collected packages: pyHik
  Running setup.py install for pyHik ... done
Successfully installed pyHik-0.0.1

verifyied installation:

# python
Python 3.5.2 (default, Nov 17 2016, 22:42:56)
[GCC 4.9.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pyhik.hikvision import HikCamera
>>> cam = HikCamera('http://a.b.c.d', '80', 'xxx', 'yyy')
>>> cam.start_stream()
>>>

....

# find /usr/ -iname *hik* -ls
58937351    0 drwxr-sr-x   3 root     staff          89 Dec  4 17:49 /usr/local/lib/python3.5/site-packages/hikvision
63069239    4 drwxr-sr-x   2 root     staff        4096 Dec  4 17:49 /usr/local/lib/python3.5/site-packages/hikvision-0.4-py3.5.egg-info
215820    4 drwxr-sr-x   4 root     root         4096 Dec  5 21:39 /usr/local/lib/python3.5/site-packages/pyhik
215837   12 -rw-r--r--   1 root     root        11426 Dec  5 21:38 /usr/local/lib/python3.5/site-packages/pyhik/hikvision.py
58986518   12 -rw-r--r--   1 root     root         8542 Dec  5 21:39 /usr/local/lib/python3.5/site-packages/pyhik/__pycache__/hikvision.cpython-35.pyc
215838    4 drwxr-sr-x   2 root     staff        4096 Dec  5 21:39 /usr/local/lib/python3.5/site-packages/pyHik-0.0.1-py3.5.egg-info
8943925    8 -rw-r--r--   1 root     root         7340 Dec  5 21:51 /usr/src/app/homeassistant/components/binary_sensor/__pycache__/hikvision.cpython-35.pyc
4593711    8 -rw-r--r--   1 root     root         6922 Dec  5 21:27 /usr/src/app/homeassistant/components/binary_sensor/hikvision.py
54720531    4 -rw-r--r--   1 root     root         3253 Dec  4 17:34 /usr/src/app/homeassistant/components/switch/hikvisioncam.py

However, when I start HA, it can’t find the pyhik package. I’m not overly familiar with HA or Python, so could be something simple:

16-12-05 21:51:39 INFO (MainThread) [homeassistant.loader] Loaded binary_sensor.hikvision from homeassistant.components.binary_sensor.hikvision
16-12-05 21:51:39 INFO (Thread-11) [homeassistant.util.package] Attempting install of pyhik==0.1
  Could not find a version that satisfies the requirement pyhik==0.1 (from versions: 0.0.1)
No matching distribution found for pyhik==0.1
16-12-05 21:51:45 ERROR (Thread-11) [homeassistant.bootstrap] Not initializing binary_sensor.hikvision because could not install dependency pyhik==0.1