UNPKG

homebridge-virtual-accessories

Version:
127 lines 6.62 kB
/* eslint-disable brace-style */ import { Accessory } from './accessory.js'; import { Timer } from '../utils/timer.js'; import { Utils } from '../utils/utils.js'; /** * FilterMaintenance - Accessory implementation */ export class FilterMaintenance extends Accessory { static ACCESSORY_TYPE_NAME = 'Filter'; static FILTER_OK = 0; // Characteristic.FilterChangeIndication.FILTER_OK static CHANGE_FILTER = 1; // Characteristic.FilterChangeIndication.CHANGE_FILTER timerStartTimeStorageKey = 'TimerStartTime'; timerDurationStorageKey = 'TimerDuration'; timerIsRunningStorageKey = 'TimerIsRunning'; lifespan; lifespanTimer; filterChangeIndicator; states = {}; constructor(platform, accessory, accessoryConfiguration) { super(platform, accessory, accessoryConfiguration); // First configure the device based on the accessory details this.lifespan = Utils.daysHoursMinutesSecondsToSeconds(this.accessoryConfiguration.filterMaintenance.lifespan.days, (this.accessoryConfiguration.filterMaintenance.lifespan.hours ??= 0), (this.accessoryConfiguration.filterMaintenance.lifespan.minutes ??= 0), (this.accessoryConfiguration.filterMaintenance.lifespan.seconds ??= 0)); const timerIsResettable = true; this.lifespanTimer = new Timer(this.accessoryConfiguration.accessoryName, this.log, timerIsResettable, this.lifespan); const accessoryState = this.loadAccessoryState(this.storagePath); if (this.isEmptyAccessoryState(accessoryState)) { // No stored state -> First run this.lifespanTimer.start(this.onTimerExpired.bind(this)); this.storeState(); } else { const cachedTimerStartTime = accessoryState[this.timerStartTimeStorageKey]; const cachedTimerDuration = accessoryState[this.timerDurationStorageKey]; const cachedTimerIsRunning = accessoryState[this.timerIsRunningStorageKey]; if (this.lifespan === cachedTimerDuration) { // If the timer was running, calculate elapsed time and set timer for remaining duration if (cachedTimerIsRunning) { Utils.restoreRunningTimer(this.lifespanTimer, cachedTimerStartTime, cachedTimerDuration, this.onTimerExpired.bind(this), this.accessoryConfiguration.accessoryName, this.log); // Do not store state if the timer was restored! // Store state only when the timer started or reset } } else { // eslint-disable-next-line max-len this.log.debug(`[${this.accessoryConfiguration.accessoryName}] Lifespan was changed from: ${cachedTimerDuration} to: ${this.lifespan}. Restart the timer`); // The lifetime was changed, restart the timer this.lifespanTimer.start(this.onTimerExpired.bind(this)); this.storeState(); } } this.filterChangeIndicator = this.lifespanTimer?.isTimerRunning() ? FilterMaintenance.FILTER_OK : FilterMaintenance.CHANGE_FILTER; this.service = this.accessory.getService(this.platform.Service.FilterMaintenance) || this.accessory.addService(this.platform.Service.FilterMaintenance); this.service.setCharacteristic(this.platform.Characteristic.Name, this.accessoryConfiguration.accessoryName); this.service.getCharacteristic(this.platform.Characteristic.FilterChangeIndication) .onGet(this.getFilterChangeIndication.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.FilterLifeLevel) .onGet(this.getFilterLifeLevel.bind(this)); this.service.getCharacteristic(this.platform.Characteristic.ResetFilterIndication) .onSet(this.setResetFilterIndication.bind(this)); } // Handlers async getFilterChangeIndication() { const filterChangeIndicator = this.filterChangeIndicator; this.log.debug(`[${this.accessoryConfiguration.accessoryName}] Getting Filter Change Indication: ${FilterMaintenance.getStateName(filterChangeIndicator)}`); return filterChangeIndicator; } async getFilterLifeLevel() { const filterLifeLevel = this.lifespanTimer.getRemainingDuration() / this.lifespan * 100; this.log.debug(`[${this.accessoryConfiguration.accessoryName}] Getting Filter Life Level: ${filterLifeLevel.toFixed(2)}%`); return filterLifeLevel; } async setResetFilterIndication(value) { const reset = value; if (reset === 1) { this.lifespanTimer.stop(); this.lifespanTimer.start(this.onTimerExpired.bind(this)); this.filterChangeIndicator = FilterMaintenance.FILTER_OK; this.storeState(); this.log.info(`[${this.accessoryConfiguration.accessoryName}] Reset Filter Indication`); } else { this.log.error(`[${this.accessoryConfiguration.accessoryName}] Reset Filter Indication called with invalid value ${reset}`); } } getJsonState() { const timerStartTime = this.lifespanTimer.getStartTime().toString(); const timerDuration = (this.lifespanTimer.getRuntime() > 0) ? this.lifespanTimer.getRuntime() : this.lifespanTimer.getDefaultDuration(); const timerIsRunning = this.lifespanTimer.isTimerRunning(); const jsonState = { [this.timerStartTimeStorageKey]: timerStartTime, [this.timerDurationStorageKey]: timerDuration, [this.timerIsRunningStorageKey]: timerIsRunning, }; const json = JSON.stringify(jsonState); return json; } getAccessoryTypeName() { return FilterMaintenance.ACCESSORY_TYPE_NAME; } static getStateName(event) { let stateName; switch (event) { case undefined: { stateName = 'undefined'; break; } case FilterMaintenance.FILTER_OK: { stateName = 'FILTER OK'; break; } case FilterMaintenance.CHANGE_FILTER: { stateName = 'CHANGE FILTER'; break; } default: { stateName = event.toString(); } } return stateName; } onTimerExpired() { this.filterChangeIndicator = FilterMaintenance.CHANGE_FILTER; this.storeState(); this.log.info(`[${this.accessoryConfiguration.accessoryName}] Filter lifetime expired`); } } //# sourceMappingURL=virtualAccessoryFilterMaintenance.js.map