From 44f75c0762c3d8b93470fb9175fe402f0da0aa11 Mon Sep 17 00:00:00 2001 From: Jason Date: Thu, 7 Mar 2019 20:05:47 -0800 Subject: [PATCH] feat(poll-state): Added Interval Units Added Interval Units and check for extra spaces around entity id --- nodes/poll-state/poll-state.html | 18 ++-- nodes/poll-state/poll-state.js | 150 ++++++++++++++++--------------- 2 files changed, 89 insertions(+), 79 deletions(-) diff --git a/nodes/poll-state/poll-state.html b/nodes/poll-state/poll-state.html index e758853de1..521a6ab42c 100644 --- a/nodes/poll-state/poll-state.html +++ b/nodes/poll-state/poll-state.html @@ -13,6 +13,7 @@ name: { value: "" }, server: { value: "", type: "server", required: true }, updateinterval: { value: "10", validate: v => !isNaN(v) }, + updateIntervalUnits: { value: "seconds" }, outputinitially: { value: false }, outputonchanged: { value: false }, entity_id: { @@ -103,7 +104,9 @@ }); }, oneditsave: function() { - this.entity_id = $("#entity_id").val(); + this.entity_id = $("#entity_id") + .val() + .trim(); const outputs = $("#node-input-halt_if").val() ? 2 : 1; $("#node-input-outputs").val(outputs); }, @@ -134,8 +137,13 @@
- - Seconds + + +
@@ -183,10 +191,10 @@

Config

Update Intervalnumber
-
Number of seconds between checking / sending updates
+
The amount of time between checking / sending updates
Half Ifstring
-
If the new_state === this setting then skip sending
+
If the new state equals this value the message will be sent to the second output
State Typestring
Convert the state of the entity to the selected type. Boolean will be convert to true based on if the string is equial by default to (y|yes|true|on|home|open). Original value stored in msg.data.original_state
diff --git a/nodes/poll-state/poll-state.js b/nodes/poll-state/poll-state.js index aad7f4e058..7091adc8b2 100644 --- a/nodes/poll-state/poll-state.js +++ b/nodes/poll-state/poll-state.js @@ -7,6 +7,7 @@ module.exports = function(RED) { config: { entity_id: {}, updateinterval: {}, + updateIntervalUnits: {}, outputinitially: {}, outputonchanged: {}, state_type: {}, @@ -19,30 +20,41 @@ module.exports = function(RED) { class TimeSinceStateNode extends EventsNode { constructor(nodeDefinition) { super(nodeDefinition, RED, nodeOptions); + this.entityId = (this.nodeConfig.entity_id || '').trim(); this.init(); } init() { - if (!this.nodeConfig.entity_id) - throw new Error('Entity ID is required'); + if (!this.entityId) { + throw new Error('Entity Id is required'); + } if (!this.timer) { const interval = !this.nodeConfig.updateinterval || parseInt(this.nodeConfig.updateinterval) < 1 - ? 1 + ? 10 : parseInt(this.nodeConfig.updateinterval); + + switch (this.nodeConfig.updateIntervalUnits) { + case 'minutes': + this.updateInterval = interval * (60 * 1000); + break; + case 'hours': + this.updateInterval = interval * (60 * 60 * 1000); + break; + default: + this.updateInterval = interval * 1000; + } this.timer = setInterval( this.onTimer.bind(this), - interval * 1000 + this.updateInterval ); } if (this.nodeConfig.outputonchanged) { this.addEventClientListener({ - event: `ha_events:state_changed:${ - this.nodeConfig.entity_id - }`, + event: `ha_events:state_changed:${this.entityId}`, handler: this.onTimer.bind(this) }); } @@ -55,7 +67,7 @@ module.exports = function(RED) { } } - onClose(removed) { + onClose() { super.onClose(); if (this.timer) { clearInterval(this.timer); @@ -67,81 +79,79 @@ module.exports = function(RED) { if (!this.isConnected) return; try { - const pollState = this.utils.merge( - {}, - await this.getState(this.nodeConfig.entity_id) + const pollState = await this.nodeConfig.server.homeAssistant.getStates( + this.entityId ); + if (!pollState) { this.warn( - `could not find state with entity_id "${ - this.nodeConfig.entity_id - }"` + `could not find state with entity_id "${this.entityId}"` ); this.status({ fill: 'red', shape: 'ring', - text: `no state found for ${this.nodeConfig.entity_id}` + text: `no state found for ${this.entityId}` }); return; } const dateChanged = this.calculateTimeSinceChanged(pollState); - if (dateChanged) { - pollState.timeSinceChanged = ta.ago(dateChanged); - pollState.timeSinceChangedMs = - Date.now() - dateChanged.getTime(); - - // Convert and save original state if needed - if ( - this.nodeConfig.state_type && - this.nodeConfig.state_type !== 'str' - ) { - pollState.original_state = pollState.state; - pollState.state = this.getCastValue( - this.nodeConfig.state_type, - pollState.state - ); - } - - this.nodeConfig.halt_if_compare = - this.nodeConfig.halt_if_compare || 'is'; - this.nodeConfig.halt_if_type = - this.nodeConfig.halt_if_type || 'str'; - - const shouldHaltIfState = - this.nodeConfig.halt_if && - (await this.getComparatorResult( - this.nodeConfig.halt_if_compare, - this.nodeConfig.halt_if, - pollState.state, - this.nodeConfig.halt_if_type - )); - - const msg = { - topic: this.nodeConfig.entity_id, - payload: pollState.state, - data: pollState - }; - - if (shouldHaltIfState) { - const debugMsg = `poll state: halting processing due to current state of ${ - pollState.entity_id - } matches "halt if state" option`; - this.debug(debugMsg); - this.debugToClient(debugMsg); - this.setStatusFailed(pollState.state); - return this.send([null, msg]); - } - - this.setStatusSuccess(pollState.state); - this.send([msg, null]); - } else { + if (!dateChanged) { this.warn( `could not calculate time since changed for entity_id "${ - this.nodeConfig.entity_id + this.entityId }"` ); + return; + } + pollState.timeSinceChanged = ta.ago(dateChanged); + pollState.timeSinceChangedMs = + Date.now() - dateChanged.getTime(); + + // Convert and save original state if needed + if ( + this.nodeConfig.state_type && + this.nodeConfig.state_type !== 'str' + ) { + pollState.original_state = pollState.state; + pollState.state = this.getCastValue( + this.nodeConfig.state_type, + pollState.state + ); + } + + this.nodeConfig.halt_if_compare = + this.nodeConfig.halt_if_compare || 'is'; + this.nodeConfig.halt_if_type = + this.nodeConfig.halt_if_type || 'str'; + + const shouldHaltIfState = + this.nodeConfig.halt_if && + (await this.getComparatorResult( + this.nodeConfig.halt_if_compare, + this.nodeConfig.halt_if, + pollState.state, + this.nodeConfig.halt_if_type + )); + + const msg = { + topic: this.entityId, + payload: pollState.state, + data: pollState + }; + + if (shouldHaltIfState) { + const debugMsg = `poll state: halting processing due to current state of ${ + pollState.entity_id + } matches "halt if state" option`; + this.debug(debugMsg); + this.debugToClient(debugMsg); + this.setStatusFailed(pollState.state); + return this.send([null, msg]); } + + this.setStatusSuccess(pollState.state); + this.send([msg, null]); } catch (e) { throw e; } @@ -151,14 +161,6 @@ module.exports = function(RED) { const entityLastChanged = entityState.last_changed; return new Date(entityLastChanged); } - - async getState(entityId) { - let state = await this.nodeConfig.server.homeAssistant.getStates( - this.nodeConfig.entity_id - ); - - return state; - } } RED.nodes.registerType('poll-state', TimeSinceStateNode); };