homebridge-boschcontrolpanel_bgseries
Version:
Homebridge plugin for Bosch Control Panel.
453 lines • 24 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.HB_BoschControlPanel_BGSeries = exports.BGSensorType = void 0;
const settings_1 = require("./settings");
const BGConst_1 = require("./BGConst");
const BGController_1 = require("./BGController");
const BGPoint_1 = require("./BGPoint");
const HKSecurityPanel_1 = require("./HKSecurityPanel");
const HKMotionSensor_1 = require("./HKMotionSensor");
const HKContactSensor_1 = require("./HKContactSensor");
const HKLeakSensor_1 = require("./HKLeakSensor");
const HKSmokeSensor_1 = require("./HKSmokeSensor");
const HKCOSensor_1 = require("./HKCOSensor");
const HKOutputAccessory_1 = require("./HKOutputAccessory");
const HKAlarmSensor_1 = require("./HKAlarmSensor");
var BGSensorType;
(function (BGSensorType) {
BGSensorType["MotionSensor"] = "MotionSensor";
BGSensorType["ContactSensor"] = "ContactSensor";
BGSensorType["LeakSensor"] = "LeakSensor";
BGSensorType["SmokeSensor"] = "SmokeSensor";
BGSensorType["COSensor"] = "COSensor";
})(BGSensorType = exports.BGSensorType || (exports.BGSensorType = {}));
class HB_BoschControlPanel_BGSeries {
constructor(log, config, api) {
this.log = log;
this.config = config;
this.api = api;
this.Service = this.api.hap.Service;
this.Characteristic = this.api.hap.Characteristic;
this.accessories = [];
this.CreatedAccessories = [];
this.PanelHost = '';
this.PanelPort = 14999;
this.PanelPasscode = '';
this.ForceLegacyMode = false;
this.PointsArray = {};
this.OutputsArray = {};
this.ControlPanelArray = [];
this.InitialRun = true;
this.ReceivingPanelNotification = false;
if (!this.CheckConfigPhase1()) {
log.error('Aborting plugin operation - Failed Config Phase 1 (Host, Port or Passcode error)');
return;
}
this.Panel = new BGController_1.BGController(this.PanelHost, this.PanelPort, BGConst_1.BGUserType.AutomationUser, this.PanelPasscode, this.ForceLegacyMode);
this.api.on('didFinishLaunching', () => {
this.DiscoverDevices();
});
}
configureAccessory(accessory) {
this.accessories.push(accessory);
}
// First config check
// check if panel host, port and passcode are set
CheckConfigPhase1() {
const Host = this.config.Host;
const Port = this.config.Port;
const Passcode = this.config.Passcode;
const ForceLegacyMode = this.config.ForceLegacyMode;
if (Host !== undefined && Host !== '') {
if (Port !== undefined && !isNaN(Port)) {
if (Passcode !== undefined && Passcode !== '') {
this.PanelHost = Host;
this.PanelPort = Port;
this.PanelPasscode = Passcode;
if (ForceLegacyMode !== undefined) {
this.ForceLegacyMode = ForceLegacyMode;
}
return true;
}
}
}
return false;
}
// Second config check
// Check that areas exist whitout any duplicates
// Check that points exist whitout any duplicates
// Check that outputs exit without any duplicates
CheckConfigPhase2() {
const TempPoint = [];
const TempArea = [];
const TempOutput = [];
// Points
if (this.config.Points !== undefined) {
for (const Point of this.config.Points) {
if (Point.PointNumber === undefined) {
this.log.error('Aborting: Point with undefined PointNumber found in config file.');
return false;
}
// Point in config not found in panel;
if (this.Panel.Points[Point.PointNumber] === undefined) {
this.log.error('Aborting: Point ' + Point.PointNumber + ' in config file is not configured on the panel');
return false;
}
//Check for duplicate point
if (TempPoint.indexOf(Point.PointNumber) !== -1) {
this.log.error('Aborting: Dupicate Point ' + Point.PointNumber + ' in config file');
return false;
}
TempPoint.push(Point.PointNumber);
}
}
// Areas
if (this.config.Areas !== undefined) {
for (const Area of this.config.Areas) {
if (Area.AreaNumber === undefined) {
this.log.error('Aborting: Area with undefined AreaNumber found in config file.');
return false;
}
if (this.Panel.Areas[Area.AreaNumber] === undefined) {
this.log.error('Aborting: Area ' + Area.AreaNumber + ' in config file is not configured on the panel');
return false;
}
//Check for duplicate area
if (TempArea.indexOf(Area.AreaNumber) !== -1) {
this.log.error('Aborting: Duplicate Area ' + Area.AreaNumber + ' in config file');
return false;
}
// Check for Area In Scope (coma separated number values)
if (Area.AreaInScope === undefined || Area.AreaInScope === '') {
continue;
}
else {
const ScopeStringArray = Area.AreaInScope.split(',');
const ScopeNumberArray = [];
for (let i = 0; i < ScopeStringArray.length; i++) {
// check for valid numeric area number
if (this.Panel.Areas[ScopeStringArray[i]] === undefined) {
this.log.error('Aborting: Area' + Area.AreaNumber + ', Area Scope Error in config file (invalid Area argument: \''
+ ScopeStringArray[i] + '\'');
return false;
}
// check for duplicate area
if (ScopeNumberArray.indexOf(Number(ScopeStringArray[i])) !== -1) {
this.log.error('Aborting: Area' + Area.AreaNumber + ', Area Scope Error in config file (duplicate Area argument: '
+ ScopeStringArray[i]);
return false;
}
ScopeNumberArray.push(Number(ScopeStringArray[i]));
}
}
TempArea.push(Area.AreaNumber);
}
}
// Outputs
if (this.config.Outputs !== undefined) {
for (const Output of this.config.Outputs) {
if (Output.OutputNumber === undefined) {
this.log.error('Aborting: Output with undefined OutputNumber found in config file.');
return false;
}
if (this.Panel.Outputs[Output.OutputNumber] === undefined) {
this.log.error('Aborting: Output' + Output.OutputNumber + ' in config file is not configured on the panel');
return false;
}
//Check for duplicate output
if (TempOutput.indexOf(Output.OutputNumber) !== -1) {
this.log.error('Aborting: Duplicate Output' + Output.OutputNumber + ' in config file');
return false;
}
TempOutput.push(Output.OutputNumber);
}
}
return true;
}
DiscoverOutputs() {
// Return if no Outputs are configured in config file
if (this.config.Outputs === undefined) {
return;
}
for (const Output of this.config.Outputs) {
if (Output.Active) {
this.OutputsArray[Output.OutputNumber] = new HKOutputAccessory_1.HKOutputAccessory(this, Output.OutputNumber);
}
}
}
DiscoverAreas() {
// Return if no Areas are configured in config file
if (this.config.Areas === undefined) {
return;
}
for (const Area of this.config.Areas) {
const AreaInScope = [];
const PasscodeFollowsScope = Area.PasscodeFollowsScope;
if (Area.Active) {
if (Area.AreaInScope !== undefined && Area.AreaInScope !== '') {
const ScopeStringArray = Area.AreaInScope.split(',');
for (let i = 0; i < ScopeStringArray.length; i++) {
AreaInScope.push(Number(ScopeStringArray[i]));
}
}
this.ControlPanelArray.push(new HKSecurityPanel_1.HKSecurityPanel(this, Area.AreaNumber, AreaInScope, PasscodeFollowsScope));
}
}
}
DiscoverPoints() {
// Return if no Points are configured in config file
if (this.config.Points === undefined) {
return;
}
for (const Point of this.config.Points) {
if (Point.Active) {
switch (Point.SensorType) {
case BGSensorType.MotionSensor: {
this.PointsArray[Point.PointNumber] = new HKMotionSensor_1.HKMotionSensor(this, Point.PointNumber);
break;
}
case BGSensorType.ContactSensor: {
this.PointsArray[Point.PointNumber] = new HKContactSensor_1.HKContactSensor(this, Point.PointNumber);
break;
}
case BGSensorType.LeakSensor: {
this.PointsArray[Point.PointNumber] = new HKLeakSensor_1.HKLeakSensor(this, Point.PointNumber);
break;
}
case BGSensorType.SmokeSensor: {
this.PointsArray[Point.PointNumber] = new HKSmokeSensor_1.HKSmokeSensor(this, Point.PointNumber);
break;
}
case BGSensorType.COSensor: {
this.PointsArray[Point.PointNumber] = new HKCOSensor_1.HKCOSensor(this, Point.PointNumber);
break;
}
}
}
}
}
DiscoverMasterAlarm() {
if (this.config.MasterFireAlarm) {
this.CreateMasterAlarm('Fire', 0);
}
if (this.config.MasterGazAlarm) {
this.CreateMasterAlarm('Gaz', 0);
}
if (this.config.MasterBurglaryAlarm) {
this.CreateMasterAlarm('Burglary', 0);
}
if (this.config.MasterPersonnalAlarm) {
this.CreateMasterAlarm('Personnal', 0);
}
}
DeviceCacheCleanUp() {
// Do some cleanup of point that have been restored and are not in config file anymore
for (let i = 0; i < this.accessories.length; i++) {
if (this.CreatedAccessories.indexOf(this.accessories[i]) === -1) {
this.api.unregisterPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [this.accessories[i]]);
}
}
}
DiscoverDevices() {
this.log.info('Configuring Panel, this may take a few minutes ...');
this.Panel.on('PanelReadyForOperation', () => {
// Phase 2 config file check
if (!this.CheckConfigPhase2()) {
this.log.error('Aborting plugin operation - Failed Config Phase 2');
return;
}
this.DumpPanelInfo();
if (this.InitialRun) {
this.log.info('-----------------------------------------');
this.log.info('Configuring Homebridge plugin accessories');
this.log.info('-----------------------------------------');
this.DiscoverAreas();
this.DiscoverPoints();
this.DiscoverOutputs();
this.DiscoverMasterAlarm();
this.DeviceCacheCleanUp();
this.InitialRun = false;
}
// Start panel event notifications.
this.log.info('-----------------------------------------');
this.log.info('Starting Control Panel Operation');
this.log.info('-----------------------------------------');
this.Panel.StartOperation();
});
this.Panel.on('PanelReceivingNotifiation', (PanelReceivingNotification) => {
if (!PanelReceivingNotification) {
// fault device
}
});
this.Panel.on('PointStatusChange', (Point) => {
const message = 'Panel: Point' + Point.PointNumber + '(' + Point.PointText + '): ' + BGPoint_1.BGPointStatus[Point.PointStatus];
this.AdvanceLog(this.config.LogPoint, message);
if (this.PointsArray[Point.PointNumber] !== undefined) {
this.PointsArray[Point.PointNumber].HandleEventDetected(Point.PointStatus);
}
});
this.Panel.on('OutputStateChange', (Output) => {
const message = 'Panel: Output' + Output.OutputNumber + '(' + Output.OutputText + '): ' + Output.OutputState;
this.AdvanceLog(this.config.LogOutput, message);
if (this.OutputsArray[Output.OutputNumber] !== undefined) {
this.OutputsArray[Output.OutputNumber].HandleOutputChange(Output.OutputState);
}
});
this.Panel.on('AreaAlarmStateChange', (Area) => {
if (Area.GetIsAlarmNominal()) {
const message = 'Panel: Area' + Area.AreaNumber + '(' + Area.AreaText + '): AlarmState: Normal';
this.AdvanceLog(this.config.LogAreaAlarm, message);
}
else {
const FireAlarm = Area.GetFireAlarm();
if (FireAlarm.length > 0) {
for (const Alarm of FireAlarm) {
const message = 'Panel: Area' + Area.AreaNumber + '(' + Area.AreaText + '): Fire - ' + BGConst_1.BGAlarmPriority[Alarm];
this.AdvanceLog(this.config.LogAreaAlarm, message);
}
}
const BurglaryAlarm = Area.GetBurglaryAlarm();
if (BurglaryAlarm.length > 0) {
for (const Alarm of BurglaryAlarm) {
const message = 'Panel: Area' + Area.AreaNumber + '(' + Area.AreaText + '): Burglary - ' + BGConst_1.BGAlarmPriority[Alarm];
this.AdvanceLog(this.config.LogAreaAlarm, message);
}
}
const GazAlarm = Area.GetGazAlarm();
if (GazAlarm.length > 0) {
for (const Alarm of GazAlarm) {
const message = 'Panel: Area' + Area.AreaNumber + '(' + Area.AreaText + '): Gas - ' + BGConst_1.BGAlarmPriority[Alarm];
this.AdvanceLog(this.config.LogAreaAlarm, message);
}
}
const PersonnalAlarm = Area.GetPersonnalAlarm();
if (PersonnalAlarm.length > 0) {
for (const Alarm of BurglaryAlarm) {
const message = 'Panel: Area' + Area.AreaNumber + '(' + Area.AreaText + '): Personnal - ' + BGConst_1.BGAlarmPriority[Alarm];
this.AdvanceLog(this.config.LogAreaAlarm, message);
}
}
}
});
// Set notification management for Confidence messages sent by panel
this.Panel.on('ConfidenceMessage', () => {
const message = 'Panel: Received Confidence Message';
this.AdvanceLog(this.config.LogConfidenceMessage, message);
this.ReceivingPanelNotification = true;
});
this.Panel.on('AreaOnOffStateChange', (Area) => {
const message = 'Panel: Area' + Area.AreaNumber + '(' + Area.AreaText + '): ' + BGConst_1.BGAreaStatus[Area.AreaStatus];
this.AdvanceLog(this.config.LogAreaArmingStatus, message);
});
this.Panel.on('ControllerError', (Error, ErrorString) => {
this.log.error(Error + ' (' + ErrorString + ')');
// Reconnect if connection to panel has been lost
if (Error === BGController_1.BGControllerError.ConnectionError) {
if (this.ReceivingPanelNotification === true) {
this.ReceivingPanelNotification = false;
this.log.info('-----------------------------------------');
this.log.info('Stopping Control Panel Operation');
this.log.info('-----------------------------------------');
}
setTimeout(() => {
this.log.info('Trying to reconnect ....');
this.Panel.Connect();
}, 60000); // Try to reconnect every 60 sec
}
});
// Start panel initialisation
this.Panel.Connect();
}
CreateMasterAlarm(MonitoringEvent, MonitoringArea) {
const uuid = this.api.hap.uuid.generate('BGMasterAlarm' + this.Panel.PanelType + MonitoringEvent + MonitoringArea);
const existingAccessory = this.accessories.find(accessory => accessory.UUID === uuid);
if (existingAccessory) {
new HKAlarmSensor_1.HKAlarmSensor(this, existingAccessory, this.Panel, MonitoringArea, MonitoringEvent);
this.CreatedAccessories.push(existingAccessory);
}
else {
const accessory = new this.api.platformAccessory('Master ' + MonitoringEvent + ' Alarm', uuid);
new HKAlarmSensor_1.HKAlarmSensor(this, accessory, this.Panel, MonitoringArea, MonitoringEvent);
this.CreatedAccessories.push(accessory);
this.api.registerPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [accessory]);
}
}
DumpPanelInfo() {
this.log.info('-----------------------------------------');
this.log.info('Bosch Control Panel Information');
this.log.info('-----------------------------------------');
this.log.info('Panel Type: ' + BGConst_1.BGPanelType[this.Panel.PanelType]);
this.log.info('Firmware: ' + this.Panel.FirmwareVersion.toSring());
this.log.info('RPS Version: ' + this.Panel.PanelRPSProtocolVersion.toSring());
this.log.info('Intrusion Protocol Version: ' + this.Panel.PanelIIPVersion.toSring());
this.log.info('Execute Protocol Version: ' + this.Panel.PanelExecuteProtocolVersion.toSring());
this.log.info('Panel Max Areas: ' + this.Panel.MaxAreas);
this.log.info('Panel Max Points: ' + this.Panel.MaxPoints);
this.log.info('Panel Max Outputs: ' + this.Panel.MaxOutputs);
this.log.info('Panel Max Users: ' + this.Panel.MaxUsers);
this.log.info('Panel Max Keypads: ' + this.Panel.MaxKeypads);
this.log.info('Panel Max Doors: ' + this.Panel.MaxDoors);
this.log.info('Panel Legacy Mode: ' + this.Panel.LegacyMode);
this.log.info('Panel Using Subscriptions: ' + this.Panel.GetPanelUsingSubscription());
if (!this.ForceLegacyMode) {
this.log.debug('Protocol 0x01: ' + this.Panel.FeatureProtocol01);
this.log.debug('Protocol 0x02: ' + this.Panel.FeatureProtocol02);
this.log.debug('Protocol 0x03: ' + this.Panel.FeatureProtocol03);
this.log.debug('Protocol 0x04: ' + this.Panel.FeatureProtocol04);
this.log.debug('Protocol 0x05: ' + this.Panel.FeatureProtocol05);
this.log.debug('Packet(512 Bytes): ' + this.Panel.Feature512BytesPacket);
this.log.debug('Packet(1460 Bytes): ' + this.Panel.Feature1460BytesPacket);
this.log.debug('Command 0x01 - WhatAreYou_CF01: ' + this.Panel.FeatureCommandWhatAreYouCF01);
//this.log.debug('Command 0x01 - WhatAreYou_CF02: ' + this.Panel.FeatureCommandWhatAreYouCF02);
this.log.debug('Command 0x01 - WhatAreYou_CF03: ' + this.Panel.FeatureCommandWhatAreYouCF03);
//this.log.debug('Command 0x01 - WhatAreYou_CF04: ' + this.Panel.FeatureCommandWhatAreYouCF04);
//this.log.debug('Command 0x01 - WhatAreYou_CF05: ' + this.Panel.FeatureCommandWhatAreYouCF05);
//this.log.debug('Command 0x01 - WhatAreYou_CF06: ' + this.Panel.FeatureCommandWhatAreYouCF06);
//this.log.debug('Command 0x01 - WhatAreYou_CF07: ' + this.Panel.FeatureCommandWhatAreYouCF07);
this.log.debug('Command 0x08 - ReqAlarmMemorySummary_CF01: ' + this.Panel.FeatureCommandReqAlarmMemorySummaryCF01);
this.log.debug('Command 0x22 - ReqAlarmAreasByPriority_CF01: ' + this.Panel.FeatureCommandReqAlarmAreasByPriorityCF01);
this.log.debug('Command 0x23 - ReqAlarmMemoryDetail_CF01: ' + this.Panel.FeatureCommandReqAlarmMemoryDetailCF01);
this.log.debug('Command 0x24 - RequestConfiguredArea_CF01: ' + this.Panel.FeatureCommandRequestConfiguredAreaCF01);
this.log.debug('Command 0x27 - ArmPanelAreas_CF01: ' + this.Panel.FeatureCommandArmPanelAreasCF01);
this.log.debug('Command 0x29 - RequestAreaText_CF01: ' + this.Panel.FeatureCommandRequestAreaTextCF01);
this.log.debug('Command 0x29 - RequestAreaText_CF03: ' + this.Panel.FeatureCommandRequestAreaTextCF03);
this.log.debug('Command 0x30 - RequestConfiguredOutputs_CF01: ' + this.Panel.FeatureCommandRequestConfiguredOutputsCF01);
this.log.debug('Command 0x32 - SetOutputState_CF01: ' + this.Panel.FeatureCommandSetOutputStateCF01);
this.log.debug('Command 0x32 - SetOutputState_CF02: ' + this.Panel.FeatureCommandSetOutputStateCF02);
this.log.debug('Command 0x33 - RequestOutputText_CF01: ' + this.Panel.FeatureCommandRequestOuputTextCF01);
this.log.debug('Command 0x33 - RequestOutputText_CF03: ' + this.Panel.FeatureCommandRequestOuputTextCF03);
this.log.debug('Command 0x36 - RequestPointsInArea_CF01: ' + this.Panel.FeatureCommandRequestPointsInAreaCF01);
this.log.debug('Command 0x3C - RequestPointText_CF01: ' + this.Panel.FeatureCommandRequestPointTextCF01);
this.log.debug('Command 0x3C - RequestPointText_CF03: ' + this.Panel.FeatureCommandRequestPointTextCF03);
this.log.debug('Command 0x5F - SetSubscription_CF01: ' + this.Panel.FeatureCommandSetSubscriptionCF01);
this.log.debug('Command 0x5F - SetSubscription_CF02: ' + this.Panel.FeatureCommandSetSubscriptionCF02);
this.log.debug('Command 0x5F - SetSubscription_CF03: ' + this.Panel.FeatureCommandSetSubscriptionCF03);
this.log.debug('Command 0x5F - SetSubscription_CF04: ' + this.Panel.FeatureCommandSetSubscriptionCF04);
this.log.debug('Command 0x5F - SetSubscription_CF05: ' + this.Panel.FeatureCommandSetSubscriptionCF05);
}
for (const AreaNumber in this.Panel.Areas) {
const Area = this.Panel.Areas[AreaNumber];
this.log.info('Area' + Area.AreaNumber + ': ' + Area.AreaText);
for (const PointNumber in this.Panel.Points) {
const Point = this.Panel.Points[PointNumber];
if (Point.AreaNumber === Area.AreaNumber) {
this.log.info(' Point' + Point.PointNumber + ': ' + Point.PointText);
}
}
}
for (const OutputNumber in this.Panel.Outputs) {
const Output = this.Panel.Outputs[OutputNumber];
this.log.info('Output' + Output.OutputNumber + ': ' + Output.OutputText);
}
}
AdvanceLog(Log, Message) {
if (Log) {
this.log.info(Message);
}
else {
this.log.debug(Message);
}
}
}
exports.HB_BoschControlPanel_BGSeries = HB_BoschControlPanel_BGSeries;
//# sourceMappingURL=platform.js.map