homebridge-boschcontrolpanel_bgseries
Version:
Homebridge plugin for Bosch Control Panel.
350 lines • 15.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BGController = exports.MaxConnectionsInUseFlags = exports.BGControllerError = void 0;
const BGConst_1 = require("./BGConst");
const BGProtocolVersion_1 = require("./BGProtocolVersion");
const tiny_typed_emitter_1 = require("tiny-typed-emitter");
const BGFirmwareVersion_1 = require("./BGFirmwareVersion");
const BGProtocolHandler01_1 = require("./BGProtocolHandler01");
const BGProtocolHandler02_1 = require("./BGProtocolHandler02");
const promise_socket_1 = require("promise-socket");
const tls = require("tls");
const net = require("net");
var BGControllerError;
(function (BGControllerError) {
BGControllerError["InvalidProtocol"] = "Invalid Protocol";
BGControllerError["InvalidProtocolLength"] = "Invalid Protocol Length";
BGControllerError["InvalidProtocolVersion"] = "Invalid Protocol Version";
BGControllerError["InvalidCommandLength"] = "Invalid Command Length";
BGControllerError["InvalidCommandFormatLength"] = "Invalid Command Format Length";
BGControllerError["InvalidResponseArgumentLength"] = "Invalid Response Length";
BGControllerError["CommandLengthOverflow"] = "Command Length Over Maximum Allowed Value";
BGControllerError["ResponseLengthOverflow"] = "Response Length Over Maximum Allowed Value";
BGControllerError["NotificationLengthOverflow"] = "Notification Length Over Maximum Allowed Value";
BGControllerError["InvalidResponseLength"] = "Invadid Response Length (Length argument)";
BGControllerError["InvalidNotificationLength"] = "Invadid Notification Length (Length argument)";
BGControllerError["BoschPanelError"] = "Bosch Panel Error";
BGControllerError["UndefinedError"] = "Undefined Error";
BGControllerError["UserNotAuthentificated"] = "User not authentificated";
BGControllerError["PanelBusy"] = "Panel is busy, cannot accept new connection";
BGControllerError["PasscodeLengthError"] = "Passcode supplied to controller is of invalid length";
BGControllerError["MaxAreaNumberError"] = "Number of configured areas over controller maximum area number";
BGControllerError["MaxOutputNumberError"] = "Number of configured outputs over controller maximum output number";
BGControllerError["ConnectionError"] = "Control Panel Connection Error";
})(BGControllerError = exports.BGControllerError || (exports.BGControllerError = {}));
var MaxConnectionsInUseFlags;
(function (MaxConnectionsInUseFlags) {
MaxConnectionsInUseFlags[MaxConnectionsInUseFlags["MaxUserBasedRemoteAccessUsersInUse"] = 4] = "MaxUserBasedRemoteAccessUsersInUse";
MaxConnectionsInUseFlags[MaxConnectionsInUseFlags["MaxAutomationUsersInUse"] = 2] = "MaxAutomationUsersInUse";
MaxConnectionsInUseFlags[MaxConnectionsInUseFlags["MaxRPSAlinkusersInUse"] = 1] = "MaxRPSAlinkusersInUse";
})(MaxConnectionsInUseFlags = exports.MaxConnectionsInUseFlags || (exports.MaxConnectionsInUseFlags = {}));
class BGController extends tiny_typed_emitter_1.TypedEmitter {
constructor(Host, Port, UserType, Passcode, ForceLegacyMode) {
super();
this.Util = require('util');
this.Semaphore = require('ts-semaphore');
this.SocktetTimeout = 180000;
this.PromiseS = new promise_socket_1.PromiseSocket();
this.MinPasscodeLength = 6;
this.MaxPassCodeLength = 24;
// Bosch Protocol related variables
this.BoschMaxAreas = 128;
this.BoschMaxPoints = 600;
this.BoschMaxOutputs = 600;
this.BoschMaxNotificationMessageBytes = 480;
// Current Panel related variables
this.PanelRPSProtocolVersion = new BGProtocolVersion_1.BGProtocolVersion(0, 0, 0);
this.PanelExecuteProtocolVersion = new BGProtocolVersion_1.BGProtocolVersion(0, 0, 0);
this.PanelIIPVersion = new BGProtocolVersion_1.BGProtocolVersion(0, 0, 0);
this.FirmwareVersion = new BGFirmwareVersion_1.BGFirmwareVersion(0, 0);
this.PanelBusyFlag = false;
this.PanelType = BGConst_1.BGPanelType.Undefined;
this.MaxAreas = 0;
this.MaxPoints = 0;
this.MaxOutputs = 0;
this.MaxUsers = 0;
this.MaxKeypads = 0;
this.MaxDoors = 0;
this.Areas = {};
this.Outputs = {};
this.Points = {};
this.PanelReadyForOperation = false;
this.PanelReceivingNotifcation = false;
// ProtocolHandler
this.Protocol01 = new BGProtocolHandler01_1.BGProtocolHandler01(this);
this.Protocol02 = new BGProtocolHandler02_1.BGProtocolHandler02(this);
this.semaphore = new this.Semaphore(1);
// Legacy options
this.LegacyMode = false;
this.InitialRun = true;
this.PoolInterval = 500;
// Panel Supported Features
this.FeatureProtocol01 = false;
this.FeatureProtocol02 = false;
this.FeatureProtocol03 = false;
this.FeatureProtocol04 = false;
this.FeatureProtocol05 = false;
this.Feature512BytesPacket = false;
this.Feature1460BytesPacket = false;
this.FeatureCommandWhatAreYouCF01 = false;
this.FeatureCommandWhatAreYouCF02 = false;
this.FeatureCommandWhatAreYouCF03 = false;
this.FeatureCommandWhatAreYouCF04 = false;
this.FeatureCommandWhatAreYouCF05 = false;
this.FeatureCommandWhatAreYouCF06 = false;
this.FeatureCommandWhatAreYouCF07 = false;
this.FeatureCommandRequestAreaTextCF01 = false;
this.FeatureCommandRequestAreaTextCF03 = false;
this.FeatureCommandRequestOuputTextCF01 = false;
this.FeatureCommandRequestOuputTextCF03 = false;
this.FeatureCommandRequestPointTextCF01 = false;
this.FeatureCommandRequestPointTextCF03 = false;
this.FeatureCommandRequestConfiguredAreaCF01 = false;
this.FeatureCommandArmPanelAreasCF01 = false;
this.FeatureCommandRequestConfiguredOutputsCF01 = false;
this.FeatureCommandRequestPointsInAreaCF01 = false;
this.FeatureCommandSetOutputStateCF01 = false;
this.FeatureCommandSetOutputStateCF02 = false;
this.FeatureCommandSetSubscriptionCF01 = false;
this.FeatureCommandSetSubscriptionCF02 = false;
this.FeatureCommandSetSubscriptionCF03 = false;
this.FeatureCommandSetSubscriptionCF04 = false;
this.FeatureCommandSetSubscriptionCF05 = false;
this.FeatureCommandReqAlarmAreasByPriorityCF01 = false;
this.FeatureCommandReqAlarmMemorySummaryCF01 = false;
this.FeatureCommandReqAlarmMemoryDetailCF01 = false;
this.Host = Host;
this.Port = Port;
this.Passcode = Passcode;
this.LegacyMode = ForceLegacyMode;
this.UserType = UserType;
this.Socket = new net.Socket();
}
Connect() {
this.Outputs = {};
this.Areas = {};
this.Points = {};
this.PanelReadyForOperation = false;
this.PanelReceivingNotifcation = false;
this.InitialRun = true;
const options = {
rejectUnauthorized: false,
//ca: [BoschCertificate20202030],
//checkServerIdentity: function () {
// return undefined;
//},
};
try {
this.Socket = tls.connect(this.Port, this.Host, options, () => {
this.PromiseS = new promise_socket_1.PromiseSocket(this.Socket);
this.Configure();
});
this.Socket.setTimeout(this.SocktetTimeout);
this.Socket.on('timeout', () => {
this.PanelReadyForOperation = false;
this.PanelReceivingNotifcation = false;
this.emit('PanelReceivingNotifiation', this.PanelReceivingNotifcation);
this.emit('ControllerError', BGControllerError.ConnectionError, 'Timeout');
this.Socket.destroy();
});
this.Socket.on('error', (error) => {
this.PanelReadyForOperation = false;
this.PanelReceivingNotifcation = false;
this.emit('PanelReceivingNotifiation', this.PanelReceivingNotifcation);
this.emit('ControllerError', BGControllerError.ConnectionError, error.message);
this.Socket.destroy();
});
this.Socket.on('data', (data) => {
const Protocol = data[0];
const Data = data.slice(1, data.length);
switch (Protocol) {
case 0x01: {
break;
}
case 0x02: {
this.Protocol02.ParseMessage(Data);
break;
}
default: {
this.emit('ControllerError', BGControllerError.InvalidProtocol, 'Received unknown protocol number from panel');
}
}
});
}
catch (e) {
this.emit('PanelReceivingNotifiation', this.PanelReceivingNotifcation);
this.emit('ControllerError', BGControllerError.ConnectionError, e.message);
this.Socket.destroy();
return;
}
}
async Configure() {
if (this.LegacyMode) {
if (!await this.Protocol01.Mode2WhatAreYou_CF01()) {
return;
}
}
else {
if (!await this.Protocol01.Mode2WhatAreYou_CF03()) {
return;
}
}
if (this.PanelType === BGConst_1.BGPanelType.Solution2000 ||
this.PanelType === BGConst_1.BGPanelType.Solution3000 ||
this.PanelType === BGConst_1.BGPanelType.AMAX2100 ||
this.PanelType === BGConst_1.BGPanelType.AMAX3000 ||
this.PanelType === BGConst_1.BGPanelType.AMAX4000) {
if (!await this.Protocol01.Mode2LoginRSCUser()) {
return;
}
}
else {
if (!await this.Protocol01.Mode2Passcode()) {
return;
}
}
if (!await this.Protocol01.Mode2ReqPanelCapacitie()) {
return;
}
if (!await this.Protocol01.Mode2ReqPanelSystemStatus()) {
return;
}
if (!await this.Protocol01.Mode2ReqConfiguredAreas()) {
return;
}
if (!await this.Protocol01.Mode2ReqPointsInArea()) {
return;
}
if (!await this.Protocol01.Mode2ReqConfiguredOutputs()) {
return;
}
if (this.LegacyMode || !this.FeatureCommandRequestAreaTextCF03) {
if (!await this.Protocol01.Mode2ReqAreaText_CF01()) {
return;
}
}
else {
if (!await this.Protocol01.Mode2ReqAreaText_CF03(0)) {
return;
}
}
if (this.LegacyMode || !this.FeatureCommandRequestPointTextCF03) {
if (!await this.Protocol01.Mode2ReqPointText_CF01()) {
return;
}
}
else {
if (!await this.Protocol01.Mode2ReqPointText_CF03(0)) {
return;
}
}
if (this.LegacyMode || !this.FeatureCommandRequestOuputTextCF03) {
if (!await this.Protocol01.Mode2ReqOutputText_CF01()) {
return;
}
}
else {
if (!await this.Protocol01.Mode2ReqOutputText_CF03(0)) {
return;
}
}
this.PanelReadyForOperation = true;
this.emit('PanelReadyForOperation', true);
}
async StartOperation() {
// Pool panel in LegacyMode
if (this.LegacyMode) {
this.PoolPanel();
return;
}
// Enable subscriptions if available on panel
if (this.FeatureProtocol02) {
if (this.FeatureCommandSetSubscriptionCF03 === true) {
await this.Protocol01.Mode2SetSubscriptions_CF03();
this.PanelReceivingNotifcation = true;
this.emit('PanelReceivingNotifiation', this.PanelReceivingNotifcation);
return;
}
if (this.FeatureCommandSetSubscriptionCF02 === true) {
await this.Protocol01.Mode2SetSubscriptions_CF02();
this.PanelReceivingNotifcation = true;
this.emit('PanelReceivingNotifiation', this.PanelReceivingNotifcation);
return;
}
if (this.FeatureCommandSetSubscriptionCF01 === true) {
await this.Protocol01.Mode2SetSubscriptions_CF01();
this.PanelReceivingNotifcation = true;
this.emit('PanelReceivingNotifiation', this.PanelReceivingNotifcation);
return;
}
}
// Default to Pooling Panel
this.PoolPanel();
}
async PoolPanel() {
if (!await this.Protocol01.Mode2ReqPointsStatus()) {
return;
}
if (!await this.Protocol01.Mode2ReqOutputStatus()) {
return;
}
if (!await this.Protocol01.Mode2ReqAreaStatus_CF01()) {
return;
}
if (!await this.Protocol01.Mode2ReqAlarmMemorySummary_CF01()) {
return;
}
setTimeout(() => {
this.PoolPanel();
}, this.PoolInterval);
}
GetPanelUsingSubscription() {
if (this.LegacyMode) {
return false;
}
return this.FeatureProtocol02;
}
async GetAlarmMemoryDetail(AlarmPriority, LastArea, LastPoint) {
this.semaphore.use(async () => {
await this.Protocol01.Mode2ReqAlarmMemoryDetail_CF01(AlarmPriority, LastArea, LastPoint);
});
return;
}
async GetOutputState() {
this.semaphore.use(async () => {
await this.Protocol01.Mode2ReqOutputStatus();
});
return;
}
async SetOutputState(OutputNumer, State) {
this.semaphore.use(async () => {
if (this.LegacyMode) {
await this.Protocol01.Mode2SetOutputState_CF01(OutputNumer, State);
return;
}
if (this.PanelType === BGConst_1.BGPanelType.Solution2000 ||
this.PanelType === BGConst_1.BGPanelType.Solution3000 ||
this.PanelType === BGConst_1.BGPanelType.AMAX4000 ||
this.PanelType === BGConst_1.BGPanelType.AMAX2100 ||
this.PanelType === BGConst_1.BGPanelType.AMAX3000) {
await this.Protocol01.Mode2SetOutputState_CF01(OutputNumer, State);
return;
}
if (this.FeatureCommandSetOutputStateCF02) {
await this.Protocol01.Mode2SetOutputState_CF02(OutputNumer, State);
return;
}
// Last resort
await this.Protocol01.Mode2SetOutputState_CF01(OutputNumer, State);
});
return;
}
async ArmArea(AreaToArm, ArmingType) {
this.semaphore.use(async () => {
await this.Protocol01.Mode2ArmPanelAreas(AreaToArm, ArmingType);
return;
});
}
}
exports.BGController = BGController;
//# sourceMappingURL=BGController.js.map