homebridge-hikvision-local
Version:
Homebridge plugin that connects to your HikVision DVR via a local connection and exposes your cameras in Homebridge. The plugin is heavily based on excellent [homebridge-camera-ffmpeg](https://github.com/Sunoo/homebridge-camera-ffmpeg) and the various hom
133 lines • 8.45 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.HikVisionNVR = void 0;
const HikVisionCamera_1 = require("./HikVisionCamera");
const HikvisionApi_1 = require("./HikvisionApi");
const logger_1 = require("./lib/logger");
const _1 = require(".");
class HikVisionNVR {
constructor(log, config, api) {
this.log = new logger_1.Log(log, config.debug);
this.homebridgeApi = api;
this.hikVisionApi = new HikvisionApi_1.HikvisionApi(config, this.log);
this.config = config;
this.cameras = [];
this.log.info('Initialising accessories for HikVision...');
this.homebridgeApi.on('didFinishLaunching', this.loadAccessories.bind(this));
setInterval(this.loadAccessories.bind(this), (this.config.refresh ? this.config.refresh * 60 * 60 * 1000 : 12 * 60 * 60 * 1000));
}
loadAccessories() {
return __awaiter(this, void 0, void 0, function* () {
this.log.info(`Connecting to NVR system @ ${this.hikVisionApi._baseURL}`);
const systemInformation = yield this.hikVisionApi.getSystemInfo();
if (this.hikVisionApi.connected) {
this.log.info(`Connected to NVR system: @ ${this.hikVisionApi._baseURL} -> '${systemInformation.DeviceInfo.deviceName}' ${systemInformation.DeviceInfo.model}`);
this.log.info('Loading cameras...');
const apiCameras = yield this.hikVisionApi.getCameras();
this.log.debug(`Found cameras: ${JSON.stringify(apiCameras, null, 2)}`);
apiCameras.map((channel) => {
var _a, _b, _c;
if (!channel.capabilities.StreamingChannel) {
this.log.error(`Failed to connect to NVR system, incomplete config @ ${this.hikVisionApi._baseURL}`);
return;
}
const cameraConfig = {
accessory: 'camera',
name: (this.config.test ? 'Test ' : '') + channel.name,
channelId: channel.id,
hasAudio: channel.capabilities ? String(channel.capabilities.StreamingChannel.Audio.enabled._) == 'true' : false,
doorbell: (((_a = this.config) === null || _a === void 0 ? void 0 : _a.doorbells) ? (_b = this.config) === null || _b === void 0 ? void 0 : _b.doorbells.includes(channel.name) : false),
model: (_c = channel.sourceInputPortDescriptor) === null || _c === void 0 ? void 0 : _c.model,
};
const cameraUUID = this.homebridgeApi.hap.uuid.generate((this.config.test ? 'Test ' : '') + _1.HIKVISION_PLUGIN_NAME + systemInformation.DeviceInfo.deviceID + cameraConfig.channelId);
let accessoryType = 17 /* this.homebridgeApi.hap.Accessory.Categories.CAMERA */;
if (cameraConfig.doorbell) {
accessoryType = 18 /* this.homebridgeApi.hap.Accessory.Categories.VIDEO_DOORBELL */;
}
const accessory = new this.homebridgeApi.platformAccessory(cameraConfig.name, cameraUUID, accessoryType);
accessory.context = cameraConfig;
// Only add new cameras that are not cached
if (!this.cameras.find((x) => x.UUID === accessory.UUID)) {
this.configureAccessory(accessory); // abusing the configureAccessory here
this.homebridgeApi.publishExternalAccessories(_1.HIKVISION_PLUGIN_NAME, [accessory]);
}
return accessory;
});
this.log.info('Registering cameras with homebridge');
this.startMonitoring();
}
else {
this.log.error(`Failed to connect to NVR system @ ${this.hikVisionApi._baseURL}`);
}
// var camerasToRemove: any[] = [];
// // Remove cameras that were not in previous call
// this.cameras.forEach((camera: any) => {
// if (!newAccessories.find((x: PlatformAccessory) => x.UUID === camera.UUID)) {
// this.log(`Unregistering missing camera: ${camera.UUID}`)
// camerasToRemove.push(camera.accessory);
// }
// });
// this.homebridgeApi.unregisterPlatformAccessories(HIKVISION_PLUGIN_NAME, HIKVISION_PLATFORM_NAME, camerasToRemove);
});
}
configureAccessory(accessory) {
return __awaiter(this, void 0, void 0, function* () {
accessory.context = Object.assign(accessory.context, this.config);
const camera = new HikVisionCamera_1.HikVisionCamera(this.log, this.homebridgeApi, accessory, this.config);
const cameraAccessoryInfo = camera.getService(this.homebridgeApi.hap.Service.AccessoryInformation);
cameraAccessoryInfo.setCharacteristic(this.homebridgeApi.hap.Characteristic.Manufacturer, 'HikVision');
cameraAccessoryInfo.setCharacteristic(this.homebridgeApi.hap.Characteristic.Model, accessory.context.model);
// cameraAccessoryInfo!.setCharacteristic(this.homebridgeApi.hap.Characteristic.SerialNumber, systemInformation.DeviceInfo.serialNumber);
// cameraAccessoryInfo!.setCharacteristic(this.homebridgeApi.hap.Characteristic.FirmwareRevision, systemInformation.DeviceInfo.firmwareVersion);
this.cameras.push(camera);
});
}
processHikVisionEvent(event) {
switch (event.EventNotificationAlert.eventType) {
case 'videoloss':
this.log.debug('videoloss, nothing to do...');
break;
case 'fielddetection':
case 'linedetection':
case 'shelteralarm':
case 'VMD':
const motionDetected = event.EventNotificationAlert.eventState === 'active';
const channelId = (event.EventNotificationAlert.channelID ? event.EventNotificationAlert.channelID : event.EventNotificationAlert.dynChannelID);
const camera = this.cameras.find((data) => data.accessory.context.channelId === channelId);
if (!camera) {
return this.log.warn(`Could not find camera for event ${event}`);
}
this.log.info(`Motion detected on camera, triggering motion for ${camera.displayName}`);
if (motionDetected !== camera.motionDetected) {
camera.motionDetected = motionDetected;
const motionService = camera.getService(this.homebridgeApi.hap.Service.MotionSensor);
motionService === null || motionService === void 0 ? void 0 : motionService.setCharacteristic(this.homebridgeApi.hap.Characteristic.MotionDetected, motionDetected);
setTimeout(() => {
var _a;
this.log.debug(`Disabling motion detection on camera ${camera.displayName}`);
camera.motionDetected = !motionDetected;
(_a = camera
.getService(this.homebridgeApi.hap.Service.MotionSensor)) === null || _a === void 0 ? void 0 : _a.setCharacteristic(this.homebridgeApi.hap.Characteristic.MotionDetected, !motionDetected);
}, 10000);
}
default:
this.log.debug(`event ${event}`);
}
}
startMonitoring() {
if (this.hikVisionApi.connected) {
this.hikVisionApi.startMonitoringEvents(this.processHikVisionEvent.bind(this));
}
}
}
exports.HikVisionNVR = HikVisionNVR;
//# sourceMappingURL=HikVisionNVR.js.map