UNPKG

@homebridge-plugins/homebridge-smarthq

Version:

The SmartHQ plugin allows you to interact with SmartHQ Devices in HomeKit and with Siri.

307 lines 13.1 kB
import axios from 'axios'; import { interval, startWith } from 'rxjs'; import { ERD_TYPES } from '../settings.js'; import { deviceBase } from './device.js'; var FanSpeed; (function (FanSpeed) { FanSpeed["OFF"] = "00"; FanSpeed["LOW"] = "01"; FanSpeed["MEDIUM"] = "02"; FanSpeed["HIGH"] = "03"; FanSpeed["BOOST"] = "04"; })(FanSpeed || (FanSpeed = {})); var LightLevel; (function (LightLevel) { LightLevel["OFF"] = "00"; LightLevel["DIM"] = "01"; LightLevel["HIGH"] = "02"; })(LightLevel || (LightLevel = {})); export class SmartHQHood extends deviceBase { platform; accessory; device; FAN_SVC_NAME = 'HOOD_FAN'; LIGHT_SVC_NAME = 'HOOD_LIGHT'; fanSvc; lightSvc; constructor(platform, accessory, device) { super(platform, accessory, device); this.platform = platform; this.accessory = accessory; this.device = device; this.fanSvc = this.accessory.getService(this.FAN_SVC_NAME) ?? this.accessory.addService(this.platform.Service.Fanv2, `${accessory.displayName} Fan`, this.FAN_SVC_NAME); this.lightSvc = this.accessory.getService(this.LIGHT_SVC_NAME) ?? this.accessory.addService(this.platform.Service.Lightbulb, `${accessory.displayName} Light`, this.LIGHT_SVC_NAME); const fanSwitchSvc = this.accessory.getService('HOOD_FAN_SWITCH'); if (fanSwitchSvc) { this.accessory.removeService(fanSwitchSvc); } const lightSwitchSvc = this.accessory.getService('HOOD_LIGHT_SWITCH'); if (lightSwitchSvc) { this.accessory.removeService(lightSwitchSvc); } this.fanSvc .getCharacteristic(this.platform.Characteristic.Active) .onGet(this.handleGetFanActive.bind(this)) .onSet(this.handleSetFanActive.bind(this)); this.fanSvc .getCharacteristic(this.platform.Characteristic.RotationSpeed) .setProps({ minValue: 0, maxValue: 100, minStep: 25, }) .onGet(this.handleGetFanRotationSpeed.bind(this)) .onSet(this.handleSetFanRotationSpeed.bind(this)); this.lightSvc .getCharacteristic(this.platform.Characteristic.On) .onGet(this.handleGetLightOn.bind(this)) .onSet(this.handleSetLightOn.bind(this)); this.lightSvc .getCharacteristic(this.platform.Characteristic.Brightness) .setProps({ minValue: 0, maxValue: 100, minStep: 50, }) .onGet(this.handleGetLightBrightness.bind(this)) .onSet(this.handleSetLightBrightness.bind(this)); interval(this.deviceRefreshRate * 1000) .pipe(startWith(0)) .subscribe(this.refreshState.bind(this)); } getErdValue(erd) { return axios .get(`/appliance/${this.accessory.context.device.applianceId}/erd/${erd}`) .then(response => response.data.value) .catch((err) => { const message = axios.isAxiosError(err) && err.response ? `Failed to fetch ERD: ${err.response.data.message}` : `Failed to fetch ERD: ${err instanceof Error ? err.message : 'An unknown error occurred'}`; throw new Error(message, { cause: err }); }); } setErdValue(erd, value) { return axios .post(`/appliance/${this.accessory.context.device.applianceId}/erd/${erd}`, { kind: 'appliance#erdListEntry', userId: this.accessory.context.userId, applianceId: this.accessory.context.device.applianceId, erd, value, }) .then(() => { this.platform.log.debug(`[${this.accessory.displayName}] Set ERD ${erd}=${value}`); }) .catch((err) => { const message = axios.isAxiosError(err) && err.response ? `Failed to set ERD ${erd}=${value}: ${err.response.data.message}` : `Failed to set ERD ${erd}=${value}: ${err instanceof Error ? err.message : 'An unknown error occurred'}`; throw new Error(message, { cause: err }); }); } getFanSpeed() { return this.getErdValue(ERD_TYPES.HOOD_FAN_SPEED) .then(value => value) .catch((err) => { throw new Error(`Failed to get fan speed: ${err instanceof Error ? err.message : 'An unknown error occurred'}`, { cause: err }); }); } setFanSpeed(value) { return this.setErdValue(ERD_TYPES.HOOD_FAN_SPEED, value) .catch((err) => { throw new Error(`Failed to set fan speed: ${err instanceof Error ? err.message : 'An unknown error occurred'}`, { cause: err }); }); } getLightLevel() { return this.getErdValue(ERD_TYPES.HOOD_LIGHT_LEVEL) .then(value => value) .catch((err) => { throw new Error(`Failed to get light level: ${err instanceof Error ? err.message : 'An unknown error occurred'}`, { cause: err }); }); } setLightLevel(value) { return this.setErdValue(ERD_TYPES.HOOD_LIGHT_LEVEL, value) .catch((err) => { throw new Error(`Failed to set light level: ${err instanceof Error ? err.message : 'An unknown error occurred'}`, { cause: err }); }); } fanSpeedToRotationSpeed(fanSpeed) { switch (fanSpeed) { case FanSpeed.OFF: return 0; case FanSpeed.LOW: return 25; case FanSpeed.MEDIUM: return 50; case FanSpeed.HIGH: return 75; case FanSpeed.BOOST: return 100; default: return 0; } } rotationSpeedToFanSpeed(rotationSpeed) { if (rotationSpeed === 0) { return FanSpeed.OFF; } if (rotationSpeed <= 25) { return FanSpeed.LOW; } if (rotationSpeed <= 50) { return FanSpeed.MEDIUM; } if (rotationSpeed <= 75) { return FanSpeed.HIGH; } return FanSpeed.BOOST; } lightLevelToBrightness(lightLevel) { switch (lightLevel) { case LightLevel.OFF: return 0; case LightLevel.DIM: return 50; case LightLevel.HIGH: return 100; default: return 0; } } brightnessToLightLevel(brightness) { if (brightness === 0) { return LightLevel.OFF; } if (brightness <= 50) { return LightLevel.DIM; } return LightLevel.HIGH; } handleGetFanActive() { return this.getFanSpeed() .then((fanSpeed) => { const isActive = fanSpeed !== FanSpeed.OFF; const value = isActive ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE; this.debugLog(`Get fan active: ${isActive}`); return value; }) .catch((err) => { this.errorLog(`handleGetFanActive failed: ${err.message}`); throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); }); } handleSetFanActive(value) { const isActive = value === this.platform.Characteristic.Active.ACTIVE; const fanSpeed = isActive ? FanSpeed.LOW : FanSpeed.OFF; this.debugLog(`Set fan active: ${isActive}`); return this.setFanSpeed(fanSpeed) .then(() => { const rotationSpeed = isActive ? 25 : 0; this.fanSvc.updateCharacteristic(this.platform.Characteristic.RotationSpeed, rotationSpeed); }) .catch((err) => { this.errorLog(`handleSetFanActive failed: ${err.message}`); throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); }); } handleGetFanRotationSpeed() { return this.getFanSpeed() .then((fanSpeed) => { const rotationSpeed = this.fanSpeedToRotationSpeed(fanSpeed); this.debugLog(`Get fan rotation speed: ${rotationSpeed}% (${fanSpeed})`); return rotationSpeed; }) .catch((err) => { this.errorLog(`handleGetFanRotationSpeed failed: ${err.message}`); throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); }); } handleSetFanRotationSpeed(value) { const rotationSpeed = value; const fanSpeed = this.rotationSpeedToFanSpeed(rotationSpeed); this.debugLog(`Set fan rotation speed: ${rotationSpeed}% -> ${fanSpeed}`); return this.setFanSpeed(fanSpeed) .then(() => { this.fanSvc.updateCharacteristic(this.platform.Characteristic.RotationSpeed, rotationSpeed); }) .catch((err) => { this.errorLog(`handleSetFanRotationSpeed failed: ${err.message}`); throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); }); } handleGetLightOn() { return this.getLightLevel() .then((lightLevel) => { const isOn = lightLevel !== LightLevel.OFF; this.debugLog(`Get light on: ${isOn}`); return isOn; }) .catch((err) => { this.errorLog(`handleGetLightOn failed: ${err.message}`); throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); }); } handleSetLightOn(value) { const isOn = value; const lightLevel = isOn ? LightLevel.DIM : LightLevel.OFF; this.debugLog(`Set light on: ${isOn}`); return this.setLightLevel(lightLevel) .then(() => { const brightness = isOn ? 50 : 0; this.lightSvc.updateCharacteristic(this.platform.Characteristic.Brightness, brightness); }) .catch((err) => { this.errorLog(`handleSetLightOn failed: ${err.message}`); throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); }); } handleGetLightBrightness() { return this.getLightLevel() .then((lightLevel) => { const brightness = this.lightLevelToBrightness(lightLevel); this.debugLog(`Get light brightness: ${brightness}% (${lightLevel})`); return brightness; }) .catch((err) => { this.errorLog(`handleGetLightBrightness failed: ${err.message}`); throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); }); } handleSetLightBrightness(value) { const brightness = value; const lightLevel = this.brightnessToLightLevel(brightness); this.debugLog(`Set light brightness: ${brightness}% -> ${lightLevel}`); return this.setLightLevel(lightLevel) .then(() => { this.lightSvc.updateCharacteristic(this.platform.Characteristic.Brightness, brightness); }) .catch((err) => { this.errorLog(`handleSetLightBrightness failed: ${err.message}`); throw new this.platform.api.hap.HapStatusError(-70402 /* this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE */); }); } refreshState() { return Promise.all([ this.getFanSpeed(), this.getLightLevel(), ]) .then(([fanSpeed, lightLevel]) => { // Treat undefined values as OFF to prevent incorrect "on" states const isActive = fanSpeed !== undefined && fanSpeed !== FanSpeed.OFF; const rotationSpeed = this.fanSpeedToRotationSpeed(fanSpeed); const isOn = lightLevel !== undefined && lightLevel !== LightLevel.OFF; const brightness = this.lightLevelToBrightness(lightLevel); this.fanSvc.updateCharacteristic(this.platform.Characteristic.Active, isActive ? this.platform.Characteristic.Active.ACTIVE : this.platform.Characteristic.Active.INACTIVE); this.fanSvc.updateCharacteristic(this.platform.Characteristic.RotationSpeed, rotationSpeed); this.lightSvc.updateCharacteristic(this.platform.Characteristic.On, isOn); this.lightSvc.updateCharacteristic(this.platform.Characteristic.Brightness, brightness); this.debugLog(`State refreshed - Fan: ${fanSpeed} (${rotationSpeed}%), Light: ${lightLevel} (${brightness}%)`); }) .catch((err) => { this.errorLog(`Failed to refresh state: ${err.message}`); }); } } //# sourceMappingURL=hood.js.map