homebridge-ikettle
Version:
Simple HomeKit control for your iKettle. Easy access without faffing with Siri Shortcuts/IFTTT.
159 lines • 7.92 kB
JavaScript
import { iKettleService } from './iKettleService.js';
/**
* Platform Accessory
* An instance of this class is created for each accessory your platform registers
* Each accessory may expose multiple services of different service types.
*/
export class iKettlePlatformAccessory {
platform;
accessory;
deviceId;
userId;
deviceDetails;
log;
kettleManager;
heaterService;
constructor(platform, accessory) {
this.platform = platform;
this.accessory = accessory;
this.log = platform.log;
this.deviceDetails = this.accessory.context.device;
this.deviceId = this.deviceDetails.id;
this.userId = this.deviceDetails.id;
this.kettleManager = iKettleService.getInstance(this.log);
this.watchKettle();
accessory
.getService(platform.Service.AccessoryInformation)
.setCharacteristic(platform.Characteristic.Manufacturer, 'Smarter.Am')
.setCharacteristic(platform.Characteristic.Model, this.deviceDetails.name)
.setCharacteristic(platform.Characteristic.SerialNumber, this.deviceDetails.status.device_model)
.setCharacteristic(platform.Characteristic.FirmwareRevision, this.deviceDetails.status.firmware_version);
this.heaterService =
this.accessory.getService(this.deviceDetails.name) ||
this.accessory.addService(this.platform.Service.Thermostat, this.deviceDetails.name, this.deviceId);
this.heaterService
.getCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState)
.onGet(this.handleCurrentHeatingCoolingStateGet.bind(this));
this.heaterService
.getCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState)
.setProps({ minValue: 0, maxValue: 1, validValues: [0, 1] })
.onGet(this.handleTargetHeatingCoolingStateGet.bind(this))
.onSet(this.handleTargetHeatingCoolingStateSet.bind(this));
this.heaterService.getCharacteristic(this.platform.Characteristic.CurrentTemperature).onGet(this.handleCurrentTemperatureGet.bind(this));
this.heaterService
.getCharacteristic(this.platform.Characteristic.TargetTemperature)
.setProps({ minValue: 0, maxValue: 100, minStep: 5 })
.onGet(this.handleTargetTemperatureGet.bind(this))
.onSet(this.handleTargetTemperatureSet.bind(this));
this.heaterService
.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits)
.onGet(this.handleTemperatureDisplayUnitsGet.bind(this))
.onSet(this.handleTemperatureDisplayUnitsSet.bind(this));
this.heaterService.getCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity).onGet(this.getWaterLevel.bind(this));
}
async handleCurrentHeatingCoolingStateGet() {
this.log.debug('Triggered GET CurrentHeatingCoolingState');
if (this.deviceDetails.status.state === 'Idle') {
return this.platform.Characteristic.CurrentHeatingCoolingState.OFF;
}
if (this.deviceDetails.status.state === 'Boiling') {
return this.platform.Characteristic.CurrentHeatingCoolingState.HEAT;
}
this.log.error('Unknown kettle state', this.deviceDetails.status.state);
return this.platform.Characteristic.CurrentHeatingCoolingState.OFF;
}
async handleTargetHeatingCoolingStateGet() {
this.log.debug('Triggered GET TargetHeatingCoolingState');
if (this.deviceDetails.status.state === 'Idle') {
return this.platform.Characteristic.TargetHeatingCoolingState.OFF;
}
if (this.deviceDetails.status.state === 'Boiling') {
return this.platform.Characteristic.TargetHeatingCoolingState.HEAT;
}
this.log.error('Unknown kettle state', this.deviceDetails.status.state);
return this.platform.Characteristic.TargetHeatingCoolingState.OFF;
}
async handleTargetHeatingCoolingStateSet(value) {
this.log.debug('Triggered SET TargetHeatingCoolingState:', value);
if (value == this.platform.Characteristic.TargetHeatingCoolingState.HEAT) {
this.log.info('Boiling kettle');
this.kettleManager.startBoil(this.userId, this.deviceId);
return;
}
if (value == this.platform.Characteristic.TargetHeatingCoolingState.OFF) {
this.log.info('Stopping kettle');
this.kettleManager.stopBoil(this.userId, this.deviceId);
return;
}
this.log.error('Invalid heating state, please use only off/heat');
this.handleTargetHeatingCoolingStateGet();
}
async handleCurrentTemperatureGet() {
this.log.debug('Triggered GET CurrentTemperature');
const currentValue = this.deviceDetails.status.water_temperature;
return currentValue;
}
async handleTargetTemperatureGet() {
this.log.debug('Triggered GET TargetTemperature');
return this.deviceDetails.status.boil_temperature;
}
async handleTargetTemperatureSet(value) {
const parsedValue = value;
this.log.debug(`Setting target temperature: ${parsedValue}°C`);
await this.kettleManager.setBoilTemp(this.userId, this.deviceId, parsedValue);
}
async handleTemperatureDisplayUnitsGet() {
// this.log.debug('Triggered GET TemperatureDisplayUnits');
return this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS;
}
async handleTemperatureDisplayUnitsSet(value) {
// this.log.debug('Triggered SET TemperatureDisplayUnits:', value);
}
async getWaterLevel() {
return this.deviceDetails.status.water_level;
}
watchKettle() {
this.kettleManager.watchDevice(this.deviceId).subscribe({
next: (update) => {
this.log.debug('Device update received', {
id: this.deviceId,
state: update.status.state,
waterTemp: update.status.water_temperature,
waterLevel: update.status.water_level,
boilingTemp: update.status.boil_temperature
});
this.deviceDetails = update;
this.updateHomeKit();
},
error: (error) => {
this.log.error('Device details failed to update', error);
},
complete: () => {
this.log.info(`Stopped watching for updates on ${this.deviceId} - ${this.deviceDetails.name}`);
}
});
}
updateHomeKit() {
this.heaterService
.getCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState)
.updateValue(this.getCurrentHeatingCoolingState(this.deviceDetails));
this.heaterService
.getCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState)
.updateValue(this.getTargetHeatingCoolingState(this.deviceDetails));
this.heaterService
.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
.updateValue(this.deviceDetails.status.water_temperature);
this.heaterService.getCharacteristic(this.platform.Characteristic.TargetTemperature).updateValue(this.deviceDetails.status.boil_temperature);
}
getCurrentHeatingCoolingState(newState) {
return newState.status.state === 'Boiling'
? this.platform.Characteristic.CurrentHeatingCoolingState.HEAT
: this.platform.Characteristic.CurrentHeatingCoolingState.OFF;
}
getTargetHeatingCoolingState(newState) {
return newState.status.state === 'Boiling'
? this.platform.Characteristic.TargetHeatingCoolingState.HEAT
: this.platform.Characteristic.TargetHeatingCoolingState.OFF;
}
}
//# sourceMappingURL=platformAccessory.js.map