UNPKG

homebridge-econet-rheem

Version:

Homebridge plugin based on pyeconet for control of Rheem water heaters

134 lines 5.04 kB
import { TemperatureUnits } from './constants.js'; import { HOUR, MINUTE } from '../tools/time.js'; import { safeGetItem, safeSetItem, STORAGE_KEY_RECOVERY_RATES } from '../tools/storage.js'; // in degrees Celsius per hour const DEFAULT_RECOVERY_RATE = 20; const MINIMUM_RECOVERY_RATE = 1; const RECOVERY_TIMER_INTERVAL = 2 * MINUTE; export class RecoverySimulator { waterHeater; onUpdate; minRecoveryRate; defaultRecoveryRate; recoveryRates; recoveryTimer = null; serialNumber; availability; setPoint; previousSetPoint; simulatedTemp; recoveryStartTime = null; recoveryStartTemp = null; constructor(waterHeater, onUpdate) { this.waterHeater = waterHeater; this.onUpdate = onUpdate; this.serialNumber = waterHeater.serialNumber; this.availability = waterHeater.availability; this.setPoint = waterHeater.setPoint; this.previousSetPoint = this.setPoint; this.simulatedTemp = this.setPoint; this.minRecoveryRate = MINIMUM_RECOVERY_RATE * (waterHeater.units === TemperatureUnits.FAHRENHEIT ? 1.8 : 1); this.defaultRecoveryRate = DEFAULT_RECOVERY_RATE * (waterHeater.units === TemperatureUnits.FAHRENHEIT ? 1.8 : 1); this.recoveryRates = this._loadRecoveryRates() ?? [this.defaultRecoveryRate]; } currentTemp(inputTemp) { if (this.availability === 0 && !this.isRecovering) { this.simulatedTemp = inputTemp; } return this.simulatedTemp; } get isRecovering() { return this.recoveryTimer !== null; } handleUpdate(waterHeater) { if (this.setPoint !== waterHeater.setPoint) { this.previousSetPoint = this.setPoint; this.setPoint = waterHeater.setPoint; } this.availability = waterHeater.availability; if (waterHeater.isRunning && !this.isRecovering && (this.availability === 0 || this.setPoint > this.previousSetPoint)) { this._startRecoveryTimer(); return; } if (!waterHeater.isRunning && this.availability === 0) { this._stopRecoveryTimer(); this.onUpdate(); return; } if (this.setPoint < this.previousSetPoint && this.setPoint < this.simulatedTemp) { this._stopRecoveryTimer(); this.simulatedTemp = this.setPoint; this.onUpdate(); return; } if (!waterHeater.isRunning && this.isRecovering) { this._recordRecoveryRate(); this._stopRecoveryTimer(); this.simulatedTemp = this.setPoint; this.onUpdate(); return; } } get recoveryRate() { return this.recoveryRates.reduce((a, b) => a + b, 0) / this.recoveryRates.length; } _startRecoveryTimer() { if (this.recoveryTimer) { clearInterval(this.recoveryTimer); } this.recoveryStartTime = Date.now(); this.recoveryStartTemp = this.simulatedTemp; this.recoveryTimer = setInterval(() => { this._updateSimulatedTemp(); }, RECOVERY_TIMER_INTERVAL); } _stopRecoveryTimer() { if (this.recoveryTimer) { clearInterval(this.recoveryTimer); this.recoveryTimer = null; } } _updateSimulatedTemp() { if (!this.isRecovering) { return; } const tempIncrease = this.recoveryRate * (RECOVERY_TIMER_INTERVAL / HOUR); this.simulatedTemp = Math.min(this.simulatedTemp + tempIncrease, this.setPoint); this.onUpdate(); } _recordRecoveryRate() { if (!this.recoveryStartTime || !this.recoveryStartTemp) { return; } const timeElapsed = (Date.now() - this.recoveryStartTime) / HOUR; const tempDifference = this.setPoint - this.recoveryStartTemp; this.recoveryStartTime = null; this.recoveryStartTemp = null; if (timeElapsed <= 0) { return; } const rate = tempDifference / timeElapsed; if (rate < this.minRecoveryRate) { return; } this.recoveryRates.push(rate); if (this.recoveryRates.length > 3 || (this.recoveryRates.length >= 2 && this.recoveryRates[0] === this.defaultRecoveryRate)) { this.recoveryRates.shift(); } this._saveRecoveryRates(); } get recoveryRatesObject() { const objectString = safeGetItem(this.waterHeater.storageFilePath, STORAGE_KEY_RECOVERY_RATES); return objectString ? JSON.parse(objectString) : {}; } _loadRecoveryRates() { return this.recoveryRatesObject[this.serialNumber]; } _saveRecoveryRates() { const ratesObject = this.recoveryRatesObject; ratesObject[this.serialNumber] = this.recoveryRates; safeSetItem(this.waterHeater.storageFilePath, STORAGE_KEY_RECOVERY_RATES, JSON.stringify(ratesObject)); } } //# sourceMappingURL=recoverySimulator.js.map