UNPKG

homey-api

Version:
183 lines (151 loc) 4.4 kB
'use strict'; const Util = require('../../../Util'); const EventEmitter = require('../../../EventEmitter'); /** * @class * @hideconstructor * @extends EventEmitter * @memberof HomeyAPIV3.ManagerDevices.Device */ class DeviceCapability extends EventEmitter { constructor({ id, device, listener, }) { super(); this.__onCapabilityValue = this.__onCapabilityValue.bind(this); this.__onDeviceDelete = this.__onDeviceDelete.bind(this); // Set ID Object.defineProperty(this, 'id', { value: id, enumerable: true, writable: false, }); // Set Device Object.defineProperty(this, 'device', { value: device, enumerable: false, writable: false, }); // Set Listener Object.defineProperty(this, '__listener', { value: listener, enumerable: false, writable: false, }); // Set Listener Object.defineProperty(this, '__transactionIds', { value: {}, enumerable: false, writable: false, }); // Set Value Object.defineProperty(this, '__value', { value: device.capabilitiesObj ? device.capabilitiesObj[this.id] ? device.capabilitiesObj[this.id].value : null : null, enumerable: false, writable: true, }); // Set Last Changed Object.defineProperty(this, '__lastChanged', { value: device.capabilitiesObj ? device.capabilitiesObj[this.id] ? device.capabilitiesObj[this.id].lastUpdated : null : null, enumerable: false, writable: true, }); this.device.on('capability', this.__onCapabilityValue); this.device.on('delete', this.__onDeviceDelete); } __debug(...props) { this.device.__debug(`[DeviceCapability:${this.id}]`, ...props); } /** * Destroy this capability listener, and if it's the last one, unsubscribe from the device's realtime events. */ destroy() { this.emit('destroy'); this.device.off('capability', this.__onCapabilityValue); this.device.off('delete', this.__onDeviceDelete); this.removeAllListeners(); } __onCapabilityValue({ capabilityId, value, transactionId, transactionTime, }) { if (capabilityId !== this.id) return; if (this.__transactionIds[transactionId]) { delete this.__transactionIds[transactionId]; return; } const nextLastChanged = new Date(transactionTime); if (this.lastChanged != null && nextLastChanged.getTime() === this.lastChanged.getTime()) { return; } this.__value = value; this.__lastChanged = nextLastChanged; // Mutate the current device capabilitiesObj so it always reflects the last value. const capabilityReference = this.device.capabilitiesObj && this.device.capabilitiesObj[this.id]; if (capabilityReference) { capabilityReference.value = value; capabilityReference.lastUpdated = this.lastChanged; } this.__listener(value, this); } __onDeviceDelete() { this.destroy(); } /** * @type {boolean|number|string|null} */ get value() { return typeof this.__value !== 'undefined' ? this.__value : null; } /** * @type {Date|null} */ get lastChanged() { return (this.__lastChanged instanceof Date) ? this.__lastChanged : (typeof this.__lastChanged === 'string') ? new Date(this.__lastChanged) : null; } /** * Sets a new capability value. * @param {boolean|number|string} value - The new capability value * @param {object} [opts] * @param {number} [opts.duration] */ async setValue(value, opts) { const transactionId = `homey-api-${Util.uuid()}`; const transactionTime = Date.now(); this.__transactionIds[transactionId] = transactionTime; await this.device.setCapabilityValue({ value, opts, transactionId, transactionTime, capabilityId: this.id, }); this.__value = value; this.__lastChanged = transactionTime; // Mutate the current device capabilitiesObj so it always reflects the last value. const capabilityReference = this.device.capabilitiesObj && this.device.capabilitiesObj[this.id]; if (capabilityReference) { capabilityReference.value = value; capabilityReference.lastUpdated = this.lastChanged; } } } module.exports = DeviceCapability;