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
140 lines • 7.18 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HikVisionCamera = void 0;
const logger_1 = require("homebridge-camera-ffmpeg/dist/logger");
const streamingDelegate_1 = require("homebridge-camera-ffmpeg/dist/streamingDelegate");
class HikVisionCamera {
constructor(log, homebridgeApi, accessory, config) {
this.motionDetected = false;
this.log = log;
this.homebridgeApi = homebridgeApi;
this.accessory = accessory;
this.displayName = this.accessory.displayName;
this.UUID = accessory.UUID;
this.config = config;
this.configure(this.accessory);
}
getService(...args) {
return this.accessory.getService(...args);
}
configureController(...args) {
return this.accessory.configureController(...args);
}
addService(...args) {
return this.accessory.addService(...args);
}
removeService(...args) {
return this.accessory.removeService(...args);
}
on(...args) {
this.accessory.on(...args);
}
getServiceByUUIDAndSubType(uuid, subType) {
return undefined;
}
configure(accessory) {
this.log.info(`Configuring ${(this.config.doorbells && this.config.doorbells.includes(accessory.displayName) ? 'doorbell' : 'camera')} accessory: ${accessory.displayName}`);
accessory.on('identify', () => {
this.log(`${accessory.displayName} identified!`);
});
let motionSensor = accessory.getService(this.homebridgeApi.hap.Service.MotionSensor);
if (motionSensor) {
this.log.info('Re-creating motion sensor');
accessory.removeService(motionSensor);
}
else {
// this.log.warn('There was no motion sensor set up!');
}
motionSensor = new this.homebridgeApi.hap.Service.MotionSensor(accessory.displayName);
accessory.addService(motionSensor);
if (this.config.doorbells && this.config.doorbells.includes(accessory.displayName)) {
this.log.info(`Creating Doorbell Trigger: ${accessory.displayName} Doorbell Trigger`);
const doorbellService = new this.homebridgeApi.hap.Service.Doorbell(accessory.displayName + ' Doorbell');
accessory.addService(doorbellService);
const switchService = new this.homebridgeApi.hap.Service.Switch(accessory.displayName + ' Doorbell Trigger', 'DoorbellTrigger');
switchService.getCharacteristic(this.homebridgeApi.hap.Characteristic.On)
.on('set', (state, callback) => {
this.log.info(`Doorbell trigger for ${accessory.displayName} - ${state}`);
if (state) {
doorbellService.getCharacteristic(this.homebridgeApi.hap.Characteristic.ProgrammableSwitchEvent).setValue(this.homebridgeApi.hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
setTimeout(() => {
switchService.getCharacteristic(this.homebridgeApi.hap.Characteristic.On).updateValue(false);
}, 5000);
}
callback(null);
});
accessory.addService(switchService);
}
// doorbell.updateCharacteristic(hap.Characteristic.ProgrammableSwitchEvent, hap.Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS);
const channelId = accessory.context.channelId;
const cameraConfig = {
name: accessory.displayName,
videoConfig: {
source: `-rtsp_transport tcp -i rtsp://${accessory.context.username}:${accessory.context.password}@${accessory.context.host}/Streaming/Channels/${channelId}01`,
stillImageSource: `-i http${accessory.context.secure ? 's' : ''}://${accessory.context.username}:${accessory.context.password}@${accessory.context.host}/ISAPI/Streaming/channels/${channelId}01/picture?videoResolutionWidth=720`,
maxFPS: 30, // TODO: pull this from the camera to avoid ever upsampling
maxBitrate: 16384, // TODO: pull this from the camera to avoid ever upsampling
maxWidth: 1920, // TODO: pull this from the camera to avoid ever upsampling
vcodec: 'libx264',
audio: accessory.context.hasAudio,
debug: Boolean(accessory.context.debugFfmpeg),
},
};
const cameraLogger = new logger_1.Logger(this.log);
// Use the homebridge-camera-ffmpeg StreamingDelegate.
const streamingDelegate = new streamingDelegate_1.StreamingDelegate(cameraLogger, cameraConfig, this.homebridgeApi, this.homebridgeApi.hap, '');
const cameraControllerOptions = {
cameraStreamCount: 5, // HomeKit requires at least 2 streams, but 1 is also just fine
delegate: streamingDelegate,
streamingOptions: {
supportedCryptoSuites: [
0 /* this.homebridgeApi.hap.SRTPCryptoSuites.AES_CM_128_HMAC_SHA1_80 */,
],
video: {
resolutions: [
// TODO: put in the max framerates & resolutions from the camera config.
[320, 180, 30],
[320, 240, 15], // Apple Watch requires this configuration
[320, 240, 30],
[480, 270, 30],
[480, 360, 30],
[640, 360, 30],
[640, 480, 30],
[1280, 720, 30],
[1280, 960, 30],
[1920, 1080, 30],
[1600, 1200, 30],
],
codec: {
profiles: [
0 /* this.homebridgeApi.hap.H264Profile.BASELINE */,
1 /* this.homebridgeApi.hap.H264Profile.MAIN */,
2 /* this.homebridgeApi.hap.H264Profile.HIGH */,
],
levels: [
0 /* this.homebridgeApi.hap.H264Level.LEVEL3_1 */,
1 /* this.homebridgeApi.hap.H264Level.LEVEL3_2 */,
2 /* this.homebridgeApi.hap.H264Level.LEVEL4_0 */,
],
},
},
audio: {
codecs: [
{
type: "OPUS" /* AudioStreamingCodecType.OPUS */,
samplerate: 24 /* AudioStreamingSamplerate.KHZ_24 */,
},
{
type: "AAC-eld" /* AudioStreamingCodecType.AAC_ELD */,
samplerate: 16 /* AudioStreamingSamplerate.KHZ_16 */,
},
],
},
},
};
const cameraController = new this.homebridgeApi.hap.CameraController(cameraControllerOptions, true);
accessory.configureController(cameraController);
}
}
exports.HikVisionCamera = HikVisionCamera;
//# sourceMappingURL=HikVisionCamera.js.map