UNPKG

homebridge-xfinityhome

Version:

A homebridge plugin to control your Xfinity Home security system.

194 lines 10.6 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const xfinityhome_1 = require("xfinityhome"); const Accessory_1 = __importDefault(require("./Accessory")); class PanelAccessory extends Accessory_1.default { constructor(platform, accessory, device) { super(platform, accessory, device, accessory.getService(platform.Service.SecuritySystem) || accessory.addService(platform.Service.SecuritySystem)); this.platform = platform; this.accessory = accessory; this.device = device; this.armModes = ['stay', 'away', 'night', 'disarmed', 'triggered']; this.service.addOptionalCharacteristic(this.platform.CustomCharacteristic.PanelStatus); this.service.getCharacteristic(this.platform.Characteristic.SecuritySystemCurrentState) .onGet(this.getCurrentState.bind(this, false)) .on('change', this.notifyCurrentStateChange.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.SecuritySystemTargetState) .onGet(this.getTargetState.bind(this)) .onSet(this.setTargetState.bind(this)) .on('change', this.notifyTargetChange.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.StatusTampered) .onGet(this.getTampered.bind(this)) .on('change', this.notifyTamperedChange.bind(this)); this.service.getCharacteristic(this.platform.CustomCharacteristic.PanelStatus) .onGet(this.getStatus.bind(this)) .on('change', this.notifyStatusChange.bind(this)); this.service.getCharacteristic(this.platform.CustomCharacteristic.PanelArmType) .onGet(this.getArmType.bind(this)) .on('change', this.notifyArmTypeChange.bind(this)); this.device.onevent = async (event) => { if (event.mediaType === 'event/securityStateChange') { this.device.device.properties.status = event.metadata.status; this.service.updateCharacteristic(this.platform.CustomCharacteristic.PanelStatus, this.getStatus()); event.metadata.armType !== null ? this.device.device.properties.armType = event.metadata.armType : undefined; this.service.updateCharacteristic(this.platform.CustomCharacteristic.PanelArmType, this.getArmType()); this.service.updateCharacteristic(this.platform.Characteristic.SecuritySystemTargetState, this.getTargetState()); this.service.updateCharacteristic(this.platform.Characteristic.SecuritySystemCurrentState, await this.getCurrentState(true)); } }; this.device.onchange = async (_oldState, newState) => { /** Normally not updated until AFTER `onchange` function execution */ this.device.device = newState; this.service.updateCharacteristic(this.platform.Characteristic.StatusTampered, this.getTampered()); this.service.updateCharacteristic(this.platform.CustomCharacteristic.PanelStatus, this.getStatus()); this.service.updateCharacteristic(this.platform.CustomCharacteristic.PanelArmType, this.getArmType()); this.service.updateCharacteristic(this.platform.Characteristic.SecuritySystemTargetState, this.getTargetState()); this.service.updateCharacteristic(this.platform.Characteristic.SecuritySystemCurrentState, await this.getCurrentState(true)); this.accessory.context.logPath = this.logPath; this.accessory.context.device = newState; this.accessory.context.refreshToken = this.platform.xhome.refreshToken; this.platform.api.updatePlatformAccessories([this.accessory]); if (this.device.device.trouble.length && !this.getTampered()) { this.log('warn', 'Unknown trouble detected!'); this.log('warn', 'Please open an issue about this.'); this.log('warn', JSON.stringify(this.device.device.trouble, null, 2)); } if (!xfinityhome_1.status.includes(this.device.device.properties.status)) { this.log('warn', 'Unknown current state:', this.device.device.properties.status); this.log('warn', 'Please open an issue about this.'); } }; } getTargetState() { return this.armModes.indexOf(this.device.device.properties.armType || 'disarmed'); } async setTargetState(state) { if (this.platform.config.pin) { if (state === this.armModes.indexOf('disarmed')) { this.device.device.properties.armType = ''; try { await this.device.disarm(this.platform.config.pin); } catch (err) { this.log('error', 'Failed To Disarm With Error:', err); return Promise.reject(new this.StatusError(-70402 /* HAPStatus.SERVICE_COMMUNICATION_FAILURE */)); } } else { this.device.device.properties.armType = this.armModes[state]; if (this.device.device.properties.status !== 'ready') { try { await this.device.arm(this.platform.config.pin, this.armModes[state]); } catch (err) { this.log('error', 'Failed To Arm With Error:', 'NOT_READY'); this.log('debug', err); this.service.updateCharacteristic(this.platform.Characteristic.SecuritySystemTargetState, this.getTargetState()); } /*this.log('warn', 'Failed To Arm With Error:', 'NOT_ALLOWED_IN_CURRENT_STATE'); throw new this.StatusError(HAPStatus.NOT_ALLOWED_IN_CURRENT_STATE);*/ } else { try { await this.device.arm(this.platform.config.pin, this.armModes[state]); } catch (err) { this.log('error', 'Failed To Arm With Error:', err); return Promise.reject(new this.StatusError(-70402 /* HAPStatus.SERVICE_COMMUNICATION_FAILURE */)); } } } } else { this.log('warn', `Failed To ${state === this.armModes.indexOf('disarmed') ? 'Disarm' : 'Arm'} With Error:`, 'No Pin Configured'); return Promise.reject(new this.StatusError(-70411 /* HAPStatus.INSUFFICIENT_AUTHORIZATION */)); } } async notifyTargetChange(value) { if (value.newValue !== value.oldValue) { const mode = this.armModes[value.newValue].charAt(0).toUpperCase() + this.armModes[value.newValue].slice(1); this.log(1, value.newValue === this.armModes.indexOf('disarmed') ? 'Disarming...' : `Arming ${mode}...`); } } async getCurrentState(skipUpdate) { if (skipUpdate !== true) { if (this.platform.config.lazyUpdates) { process.nextTick(() => { this.device.get().catch(err => { this.log('error', 'Failed To Fetch Current State With Error:', err); // throw new this.StatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE); }); }); } else { try { const device = await this.device.get(); return device.properties.status === 'arming' ? this.armModes.indexOf('disarmed') : ((device.properties.status === 'entryDelay' && this.platform.config.entryTrigger !== false) || device.properties.status === 'alarm') ? this.armModes.indexOf('triggered') : this.armModes.indexOf(device.properties.armType || 'disarmed'); } catch (err) { this.log('error', 'Failed To Fetch Current State With Error:', err); return Promise.reject(new this.StatusError(-70402 /* HAPStatus.SERVICE_COMMUNICATION_FAILURE */)); } } } return this.device.device.properties.status === 'arming' ? this.armModes.indexOf('disarmed') : ((this.device.device.properties.status === 'entryDelay' && this.platform.config.entryTrigger !== false) || this.device.device.properties.status === 'alarm') ? this.armModes.indexOf('triggered') : this.armModes.indexOf(this.device.device.properties.armType || 'disarmed'); } async notifyCurrentStateChange(value) { if (value.newValue !== value.oldValue) { const mode = this.armModes[value.newValue].charAt(0).toUpperCase() + this.armModes[value.newValue].slice(1); setTimeout(() => { if (value.newValue === this.armModes.indexOf('triggered')) { this.log('warn', 'Alarm Triggered'); } else { this.log(1, value.newValue === this.armModes.indexOf('disarmed') ? 'Disarmed' : `Armed ${mode}`); } }, 500); } } getTampered() { return this.device.device.trouble.find(trouble => trouble.name === 'senTamp') ? 1 : 0; } async notifyTamperedChange(value) { if (value.newValue !== value.oldValue) { if (value.newValue) { this.log('warn', 'Tampered'); } else { this.log(2, 'Fixed'); } } } getStatus() { return this.device.device.properties.status.charAt(0).toUpperCase() + this.device.device.properties.status.slice(1).replace(/([A-Z])/g, ' $1').trim(); } async notifyStatusChange(value) { if (value.newValue !== value.oldValue) { this.log(4, `Status Changed To ${value.newValue}`); } } getArmType() { return (this.device.device.properties.armType.charAt(0).toUpperCase() + this.device.device.properties.armType.slice(1).replace(/([A-Z])/g, ' $1').trim()) || '(Disarmed)'; } async notifyArmTypeChange(value) { if (value.newValue !== value.oldValue) { this.log(4, `Arm Type Changed To ${value.newValue}`); } } } exports.default = PanelAccessory; //# sourceMappingURL=PanelAccessory.js.map