UNPKG

homebridge-virtual-accessories

Version:
222 lines 10.6 kB
/* eslint-disable brace-style */ import { Accessory } from './accessory.js'; import { Colors } from '../utils/colorUtils.js'; import { Utils } from '../utils/utils.js'; /** * Lightbulb - Accessory implementation */ export class Lightbulb extends Accessory { static ACCESSORY_TYPE_NAME = 'Lightbulb'; static ON = true; static OFF = false; static WHITE = 'white'; static AMBIANCE = 'ambiance'; static COLOR = 'color'; stateStorageKey = 'LightbulbState'; brightnessStorageKey = 'LightbulbBrightness'; colorTemperatureStorageKey = 'LightbulbColorTemperature'; hueStorageKey = 'LightbulbHue'; saturationStorageKey = 'LightbulbSaturation'; type = Lightbulb.WHITE; states = { LightbulbState: Lightbulb.OFF, LightbulbBrightness: 0, LightbulbColorTemperature: 2700, // Kelvin LightbulbHue: 0, LightbulbSaturation: 0, }; constructor(platform, accessory, accessoryConfiguration) { super(platform, accessory, accessoryConfiguration); this.type = this.accessoryConfiguration.lightbulb.type; // First configure the device based on the accessory details this.defaultState = this.accessoryConfiguration.lightbulb.defaultState === 'on' ? Lightbulb.ON : Lightbulb.OFF; const brightness = this.accessoryConfiguration.lightbulb.brightness; const colorTemperatureKelvin = this.accessoryConfiguration.lightbulb.colorTemperatureKelvin; const colorHex = this.accessoryConfiguration.lightbulb.colorHex; this.states.LightbulbState = this.defaultState; this.states.LightbulbBrightness = brightness; if (this.type === Lightbulb.WHITE) { this.states.LightbulbBrightness = brightness; } else if (this.type === Lightbulb.AMBIANCE) { this.states.LightbulbBrightness = brightness; this.states.LightbulbColorTemperature = colorTemperatureKelvin; } else if (this.type === Lightbulb.COLOR) { const hsl = Colors.HexToHSL(colorHex); this.states.LightbulbHue = hsl.hue; this.states.LightbulbSaturation = hsl.saturation; this.states.LightbulbBrightness = hsl.luminance; } // If the accessory is stateful retrieve stored state if (this.accessoryConfiguration.accessoryIsStateful) { const accessoryState = this.loadAccessoryState(this.storagePath); const cachedState = accessoryState[this.stateStorageKey]; const cachedBrightness = accessoryState[this.brightnessStorageKey]; const cachedColorTemperature = accessoryState[this.colorTemperatureStorageKey]; const cachedHue = accessoryState[this.hueStorageKey]; const cachedSaturation = accessoryState[this.saturationStorageKey]; if (cachedState !== undefined) { this.states.LightbulbState = cachedState; } if (cachedBrightness !== undefined) { this.states.LightbulbBrightness = cachedBrightness; } if (this.type === Lightbulb.AMBIANCE && cachedColorTemperature !== undefined) { this.states.LightbulbColorTemperature = cachedColorTemperature; } if (this.type === Lightbulb.COLOR) { if (cachedHue !== undefined) { this.states.LightbulbHue = cachedHue; } if (cachedSaturation !== undefined) { this.states.LightbulbSaturation = cachedSaturation; } } } this.service = this.accessory.getService(this.platform.Service.Lightbulb) || this.accessory.addService(this.platform.Service.Lightbulb); this.service.setCharacteristic(this.platform.Characteristic.Name, this.accessoryConfiguration.accessoryName); // Update the initial state of the accessory this.log.debug(`[${this.accessoryName}] Setting Lightbulb Current State: ${Lightbulb.getStateName(this.states.LightbulbState)}`); this.service.updateCharacteristic(this.platform.Characteristic.On, (this.states.LightbulbState)); this.service.updateCharacteristic(this.platform.Characteristic.Brightness, (this.states.LightbulbBrightness)); // register handlers this.service.getCharacteristic(this.platform.Characteristic.On) .onSet(this.setOn.bind(this)) .onGet(this.getOn.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.Brightness) .onSet(Utils.debounce(this.setBrightness.bind(this))) .onGet(this.getBrightness.bind(this)); switch (this.type) { case Lightbulb.AMBIANCE: // register handlers for the ColorTemperature Characteristic this.service.getCharacteristic(this.platform.Characteristic.ColorTemperature) .onSet(Utils.debounce(this.setColorTemperature.bind(this))) .onGet(this.getColorTemperature.bind(this)); break; case Lightbulb.COLOR: this.service.getCharacteristic(this.platform.Characteristic.Hue) .onSet(Utils.debounce(this.setHue.bind(this))) .onGet(this.getHue.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.Saturation) .onSet(Utils.debounce(this.setSaturation.bind(this))) .onGet(this.getSaturation.bind(this)); break; case Lightbulb.WHITE: // No additional characteristics break; } } // Handlers async setOn(value) { this.states.LightbulbState = value; // If brightness is 0% or 100%, ON = 100%, OFF = 0% if ((this.states.LightbulbState === Lightbulb.ON) && (this.states.LightbulbBrightness === 0)) { this.states.LightbulbBrightness = 100; this.service?.updateCharacteristic(this.platform.Characteristic.Brightness, (this.states.LightbulbBrightness)); } else if ((this.states.LightbulbState === Lightbulb.OFF) && (this.states.LightbulbBrightness === 100)) { this.states.LightbulbBrightness = 0; this.service?.updateCharacteristic(this.platform.Characteristic.Brightness, (this.states.LightbulbBrightness)); } this.storeState(); this.log.info(`[${this.accessoryName}] Setting State: ${Lightbulb.getStateName(this.states.LightbulbState)}`); } async getOn() { const lightbulbState = this.states.LightbulbState; this.log.debug(`[${this.accessoryName}] Getting State: ${Lightbulb.getStateName(lightbulbState)}`); return lightbulbState; } async setBrightness(value) { this.states.LightbulbBrightness = value; // Setting the brightness to 0 turns lightbulb OFF if ((this.states.LightbulbBrightness === 0) && (this.states.LightbulbState === Lightbulb.ON)) { this.states.LightbulbState = Lightbulb.OFF; this.service?.updateCharacteristic(this.platform.Characteristic.On, (this.states.LightbulbState)); } this.storeState(); this.log.info(`[${this.accessoryName}] Setting Brightness: ${this.states.LightbulbBrightness}%`); } async getBrightness() { const lightbulbBrightness = this.states.LightbulbBrightness; this.log.debug(`[${this.accessoryName}] Getting Brightness: ${lightbulbBrightness}%`); return lightbulbBrightness; } async setColorTemperature(miredValue) { this.states.LightbulbColorTemperature = this.miredToKelvin(miredValue); this.storeState(); this.log.debug(`[${this.accessoryName}] Setting Color Temperature: ${this.states.LightbulbColorTemperature}K (${miredValue} Mired)`); } async getColorTemperature() { const miredValue = this.kelvinToMired(this.states.LightbulbColorTemperature); this.log.debug(`[${this.accessoryName}] Getting Color Temperature: ${this.states.LightbulbColorTemperature}K (${miredValue} Mired)`); return miredValue; } async setHue(value) { this.states.LightbulbHue = value; this.storeState(); this.log.info(`[${this.accessoryName}] Setting Hue: ${this.states.LightbulbHue}º`); } async getHue() { const lightbulbHue = this.states.LightbulbHue; this.log.debug(`[${this.accessoryName}] Getting Hue: ${lightbulbHue}º`); return lightbulbHue; } async setSaturation(value) { this.states.LightbulbSaturation = value; this.storeState(); this.log.info(`[${this.accessoryName}] Setting Saturation: ${this.states.LightbulbSaturation}º`); } async getSaturation() { const lightbulbSaturation = this.states.LightbulbSaturation; this.log.debug(`[${this.accessoryName}] Getting Saturation: ${lightbulbSaturation}º`); return lightbulbSaturation; } getJsonState() { const jsonState = { [this.stateStorageKey]: this.states.LightbulbState, [this.brightnessStorageKey]: this.states.LightbulbBrightness, }; if (this.type === Lightbulb.AMBIANCE) { Object.assign(jsonState, { [this.colorTemperatureStorageKey]: this.states.LightbulbColorTemperature }); } if (this.type === Lightbulb.COLOR) { Object.assign(jsonState, { [this.hueStorageKey]: this.states.LightbulbHue }); Object.assign(jsonState, { [this.saturationStorageKey]: this.states.LightbulbSaturation }); } const json = JSON.stringify(jsonState); return json; } getAccessoryTypeName() { return Lightbulb.ACCESSORY_TYPE_NAME; } static getStateName(state) { let stateName; switch (state) { case undefined: { stateName = 'undefined'; break; } case Lightbulb.ON: { stateName = 'ON'; break; } case Lightbulb.OFF: { stateName = 'OFF'; break; } default: { stateName = state.toString(); } } return stateName; } // micro-reciprocal degrees (mired): 1,000,000 divided by the color temperature in kelvins kelvinToMired(kelvin) { return Math.round(1000000 / kelvin); } miredToKelvin(mired) { return Math.round(1000000 / mired); } } //# sourceMappingURL=virtualAccessoryLightbulb.js.map