diff --git a/utils/equipment.js b/utils/equipment.js index 6954a73..a1bc3d4 100644 --- a/utils/equipment.js +++ b/utils/equipment.js @@ -25,13 +25,23 @@ class Equipment { // Initialization of properties this.name = this.equipmentItem.name; - this.stateItem = items[this.getPropertyItemName('State')]; + this.watch = new Object(); + this.timers = new Object(); + this.timeout = new Object(); + + // Check if equipment has state item + if (this.hasProperty('State')) { + this.stateItem = items[this.getPropertyItemName('State')]; + this.watch['State'] = new watch.Watch(this.stateItem); + } else { + console.info(`Item ${this.equipmentItem.name} has no state item`) + } // Check if equipment has LowBat item if (this.hasProperty('LowBat')) { - this.watch['lowBat'] = new watch.Watch(this.getPropertyItemName('LowBat')); - this.watch['lowBat'].add({ + this.watch['LowBat'] = new watch.Watch(this.getPropertyItemName('LowBat')); + this.watch['LowBat'].add({ targetState: 'ON', alertFunc: () => { this.#notifyLowBat(); }, alertRepeat: 'PT23H' @@ -68,7 +78,7 @@ class Equipment { } } - console.debug(`Return value ${valueName} for ${this.name}: ${returnValue}`); + console.debug(`Return value for property ${propertyName} for ${this.name}: ${returnValue}`); return returnValue; } @@ -107,6 +117,113 @@ class Equipment { class Irrigation extends Equipment { constructor(equipmentItem) { super(equipmentItem); + + // Initialization of properties + this.valves = new Object(); + + // Add on/off watch rule + this.watch['State'].add({ + targetState: 'ON', + alertFunc: () => { this.#irrigationOn(); }, + endAlertFunc: () => { this.#irrigationOff(); }, + }); + + // Fetch irrigation valves and initialize as subequipment + for (let valve of this.equipmentItem.members.filter(item => { return item.tags.includes('IrrigationValve'); } )) { + try { + this.valves[valve.name] = new IrrigationValve(valve); + } catch (error) { + console.error(error); + } + } + + } + + gc() { + console.info('Deinitialization of irrigation valves for ' + this.name); + + // Delete all watchObjects + for (let valve of Object.keys(this.valves)) { + this.valves[valve].gc(); + } + + // Call function to deinitialize irrigation + super.gc(); + } + + #irrigationOn() { + console.info(`Irrigation ${this.name} received command on`); + + // Fetch valves with AutoMode enabled + let autoValves = Object.keys(this.valves).filter(element => { return this.valves[element].getValue('AutoMode', 'OFF') == 'ON'} ); + + // Skip if no valves with AutoMode enabled are available + if (autoValves.length == 0) { + console.info('No valves with AutoMode enabled available'); + this.stateItem.sendCommandIfDifferent('OFF'); + return; + } + + let totalDuration = 0; + + for (let i = 0; i < autoValves.length; i++) { + let currentValve = autoValves[i]; + let nextValve = autoValves[(i + 1)]; + let duration = time.toZDT(this.valves[currentValve].getValue('Duration', 'PT30S')).getMillisFromNow(); + + // calculate start and endtimes for valve + let startTime = time.toZDT(totalDuration) + totalDuration = totalDuration + duration; + let endTime = time.toZDT(totalDuration); + + // Set timers for valve + this.valves[currentValve].timers['autoOn'] = actions.ScriptExecution.createTimer( + startTime, + () => { + this.valves[currentValve].stateItem.sendCommandIfDifferent('ON'); + } + ); + + this.valves[currentValve].timers['autoOff'] = actions.ScriptExecution.createTimer( + endTime, + () => { + this.valves[currentValve].stateItem.sendCommandIfDifferent('OFF'); + } + ); + + // Stop irrigation after the last valve + if (nextValve == undefined) { + console.log('No further valves with autoMode enabled available'); + this.timers['autoOff'] = actions.ScriptExecution.createTimer( + endTime.plusSeconds(5), + () => { + console.debug(`Switch irrigation ${this.name} to off`) + this.stateItem.sendCommandIfDifferent('OFF'); + } + ); + } + } + } + + #irrigationOff() { + console.info(`Irrigation ${this.name} received command off`); + + if (this.timers.hasOwnProperty('autoOff') && this.timers['autoOff'].isActive()) { + console.debug(`Cancel stop timer for irrigation`); + this.timers['autoOff'].cancel(); + } + + for (let valve of Object.keys(this.valves)) { + if (this.valves[valve].timers.hasOwnProperty('autoOn') && this.valves[valve].timers['autoOn'].isActive()) { + console.debug(`Cancel start timer for valve ${valve}`); + this.valves[valve].timers['autoOn'].cancel(); + } + if (this.valves[valve].timers.hasOwnProperty('autoOff') && this.valves[valve].timers['autoOff'].isActive()) { + console.debug(`Cancel stop timer for valve ${valve}`); + this.valves[valve].timers['autoOff'].cancel(); + } + this.valves[valve].stateItem.sendCommandIfDifferent('OFF') + } } } @@ -114,11 +231,10 @@ class IrrigationValve extends Equipment { constructor(equipmentItem) { super(equipmentItem); - this.watch['state'] = new watch.Watch(this.stateItem.name); - this.watch['state'].add({ + this.watch['State'].add({ targetState: 'ON', alertFunc: () => { this.stateItem.sendCommand('OFF'); }, - alertDelay: 'PT59M' + alertDelay: 'PT30M' }); } } @@ -127,8 +243,7 @@ class TowelRadiator extends Equipment { constructor(equipmentItem) { super(equipmentItem); - this.watch['state'] = new watch.Watch(this.stateItem.name); - this.autoOff = this.watch['state'].add({ + this.watch['State'].add({ targetState: 'ON', alertFunc: () => { this.stateItem.sendCommand('OFF'); }, alertDelay: 'PT59M'