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)