@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
JavaScript
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