homebridge-homeconnect
Version:
A Homebridge plugin that connects Home Connect appliances to Apple HomeKit
60 lines • 3.43 kB
JavaScript
// Homebridge plugin for Home Connect home appliances
// Copyright © 2019-2025 Alexander Thoukydides
import { assertIsDefined, formatSeconds } from './utils.js';
// Maximum remaining program duration (Home Connect documentation specifies 38340 seconds)
const MAX_DELAY_DURATION = 86340; // (seconds)
const MAX_PROGRAM_DURATION = 86340; // (seconds)
const MAX_REMAINING_DURATION = MAX_DELAY_DURATION + MAX_PROGRAM_DURATION;
// Add remaining program time to an accessory
export function HasRemainingTime(Base) {
return class HasRemainingTime extends Base {
// Mixin constructor
constructor(...args) {
super(...args);
// Remaining duration only supported if active program switch enabled
if (!this.activeService)
return;
// Add a progress position
this.activeService.addOptionalCharacteristic(this.Characteristic.RemainingDuration);
this.activeService.getCharacteristic(this.Characteristic.RemainingDuration)
.setProps({ maxValue: MAX_REMAINING_DURATION });
// Update the status
const updateHK = this.makeSerialised(value => { this.updateRemainingTimeHK(value); }, 'idle');
this.device.on('BSH.Common.Option.StartInRelative', () => updateHK());
this.device.on('BSH.Common.Option.RemainingProgramTime', () => updateHK());
this.device.on('BSH.Common.Event.ProgramFinished', () => updateHK('idle'));
this.device.on('BSH.Common.Event.ProgramAborted', () => updateHK('idle'));
this.device.on('BSH.Common.Status.OperationState', () => updateHK(this.device.isOperationState('DelayedStart') ? 'delayed start'
: (!this.device.isOperationState('Inactive', 'Ready', 'Finished') ? 'active' : 'idle')));
}
// Deferred update of HomeKit state from Home Connect events
updateRemainingTimeHK(state) {
// Determine the remaining duration
const timeDelay = this.device.getItem('BSH.Common.Option.StartInRelative') ?? 0;
const timeRemaining = this.device.getItem('BSH.Common.Option.RemainingProgramTime') ?? 0;
let remainingDuration = 0, description;
switch (state) {
case 'delayed start':
remainingDuration = timeDelay + timeRemaining;
description = `Program will start in ${formatSeconds(timeDelay)}`
+ ` (total ${formatSeconds(remainingDuration)} remaining)`;
break;
case 'active':
remainingDuration = timeRemaining;
description = `Program has ${formatSeconds(remainingDuration)} remaining`;
break;
default:
description = 'No program running';
break;
}
// Update the characteristic if the duration has changed
assertIsDefined(this.activeService);
const prevRemainingDuration = this.activeService.getCharacteristic(this.Characteristic.RemainingDuration).value;
if (remainingDuration !== prevRemainingDuration) {
this.log.info(description);
this.activeService.updateCharacteristic(this.Characteristic.RemainingDuration, remainingDuration);
}
}
};
}
//# sourceMappingURL=has-remainingtime.js.map