Custom widget: cameras view (Hikvision)

Tags: #<Tag:0x00007f2fb149df80> #<Tag:0x00007f2fb149ddf0> #<Tag:0x00007f2fb149db20>

Hello,

I’d like to share a widget I made to view cameras. I have a set of Hikvision IP cameras, which are transmitting video to a central DVR. I wanted to be able to see a picture of the individual cameras on a tablet in my kitchen, where the windows don’t overlook one part of the house.

Cameras can export current picture as a static jpg through a web path:
http://<user>:<password>@<ip>/Streaming/Channels/1/picture

  • Widget allows for configuring any number of cameras (I have 8 and it looks ok with 8 or smaller number, I have not tested more than 8).
  • The central part of the widget shows the currently selected camera view and refreshes the picture periodically (configurable).
  • The right part of the widget shows miniature views of all cameras in one column and they also refresh periodically (another parameter - probably much less frequent refresh is ok).
  • Clicking on a miniature will change the main camera view.
  • I suppose it can work with other vendor cameras too, which export static picture over web, so there is a parameter to define the web path to the picture in the parameters

To install, you will need to also copy hv-cameras.js file to the web server root path (for example on my Ubuntu this is: /etc/openhab2/html/hv-cameras.js), unfortunately I could not find a way to implement a periodic refresh without a script.

Due to the nature of how web browser manager user/password when accessing web pages, I don’t know how this is going to work on other web browsers than Firefox. Sometimes you may need to access the cameras directly from your browser and store credentials in its cache.

Please also mind that providing incorrect credentials, due to refresh, will quickly lock you our from the cameras for 30 minutes, unless you disable the lockout in the camera preferences.


Content of hv-cameras.js as js/zip files can’t be attached here:

(function() {
    'use strict';
    angular
        .module('app', [])
        .controller('hvCameraCtrl', ['$scope', '$interval', function($scope, $interval) {
            var cfg = $scope.$parent.ngModel.config;
            if (!cfg) {
                return;
            }
            $scope.cameraUrls = [];
            $scope.mainCameraSuffix = getSuffix();
            $scope.miniatureSuffix = getSuffix();
            
            if (cfg.camera_ips) {
                var cameras = cfg.camera_ips.split(',');
                for (var i=0; i < cameras.length; i++) {
                    var url = cfg.syntax;
                    if (cameras[i]) {
                        url = url.replace(/<ip>/gi, cameras[i]);
                        if (cfg.user) {
                            url = url.replace(/<user>/gi, cfg.user);
                        }
                        if (cfg.password) {
                            url = url.replace(/<password>/gi, cfg.password);
                        }
                    }
                    $scope.cameraUrls[i] = url;
                }
            }
                    
            function getSuffix() {
                return '?_ts=' + (new Date()).getTime();
            }
                    
            this.pictureRefreshInterval = $interval(function () {
                $scope.mainCameraSuffix = getSuffix();
            }, cfg.mainRefresh * 1000);
            
            this.miniatureRefreshInterval = $interval(function () {
                $scope.miniatureSuffix = getSuffix();
            }, cfg.miniatureRefresh * 1000);
            
            $scope.$on('$destroy', function () {
                $interval.cancel(this.pictureRefreshInterval);
                $interval.cancel(this.miniatureRefreshInterval);
            });
        }]); 
})();

cameras.widget.json (2.4 KB)

6 Likes

My binding which is found here can do that for you and works great with Hikvision

Not a problem with my binding as it correctly handles authorisation for you.

Perhaps give it a try to see if it fits your needs.

1 Like

Thank you very much for the info on your binding. I was not aware of it. I will check it and see how I can use it.

I like the way you’ve laid out your cameras Pawel, are these videos or static images? How do you get around the HabPanel issue of displaying more than 6 or 8 cameras - I find thats the maximum

Hi. The widget does not use camera items but reads static images periodically from the cameras. There is no limitation to that.
But I personally resigned from using this widget and switched to the binding mentioned above. It is enough for me to show just two cameras. Does not look that nice but works well.

Thanks Pawel

Why can’t you use both? Does it require a url to work? if so I could add that ability as someone has requested the ability to ask for jpg files through the binding with urls.

What causes this limitation? I have never tried that many so what happens when you try?

It just displays a grey box and wont display the video feed

Hi matt

see attached, you can see one doesnt load and its also missing 2 other cameras. It’s not a camera issue but a limitation it appears from my searching. If the is a way around this! That would be great

http://kb.mozillazine.org/Network.http.max-persistent-connections-per-server

When you change it from 6

you get this. Issue is, I cant get HabPanel to do this, but it works fine using a Mozilla PC browser.

Thanks for the info as it gives clues if not the exact cause as to what is stopping it from working. I just added a new snapshot feature to the ipCamera binding and I think it is worth trying to see if it works around the issue as:

  1. I use keep-alive connections and some cameras do not.
  2. The binding is super fast at serving the files because the snapshot is already in ram and can be sent right away. Cameras have to wait until a keyframe is created and then compress the jpg before it can be sent.

Use this url with the latest binding.

http://192.168.xxx.xxx:54321/ipcamera.jpg

More info is in the bindings readme.