UNPKG

node-red-contrib-timeframerlt

Version:

A Trigger and Rate Limit Node to pass messages if user count has been met within a defined user time frame.

146 lines (122 loc) 5 kB
module.exports = function(RED) { "use strict"; //Thanks to allot of code written by Daniel 'Eisbehr' Kern and his [node-red-contrib-throttle](http://github.com/eisbehr-/node-red-throttle). I based and copied allot of code off his work as his node did not quite do what i needed. function timeframerlt(config) { RED.nodes.createNode(this, config); var node = this; // config this.throttleType = config.throttleType || "count"; this.timeLimitType = config.timeLimitType || "seconds"; this.timeLimit = Number(config.timeLimit || 0); this.countLimit = Number(config.countLimit || 0); this.byresetcountLimit = Number(config.byresetcountLimit || 0); // helpers this.time = Math.floor(Date.now()); this.count = 0; this.reset = false; // calculate time limit in milliseconds if( this.timeLimitType === "hours" ) { this.timeLimit *= 60 * 60 * 1000; } else if( this.timeLimitType === "minutes" ) { this.timeLimit *= 60 * 1000; } else if( this.timeLimitType === "seconds" ) { this.timeLimit *= 1000; } // Node Status Icon - waiting for msg clear status if( node.count == 0 ) { node.status({ }); } this.on("input", function(msg) { // time frame if( isNaN(node.timeLimit) || !isFinite(node.timeLimit) ) { return this.error("time limit is not numeric", msg); } var now = Math.floor(Date.now()); var status_reset = function() { node.status({ fill: 'yellow', shape: 'dot', text: 'reset' }); }; var status_waitingformsg = function() { node.status({ }); }; var status_waitingformsgreset = function() { node.status({ fill: 'red', shape: 'ring', text: 'waiting for manual msg.reset' }); }; var status_sent = function() { node.status({ fill: 'green', shape: 'dot', text: 'sent' }); }; var status_count = function() { node.status({ fill: 'blue', shape: 'dot', text: 'msg ' + node.count + ' of ' + node.countLimit }); }; // timelimit if ( node.reset === true ) { setTimeout(status_waitingformsgreset, 0); } else if( node.time + node.timeLimit < now ) { node.time = now; node.count = 0; setTimeout(status_reset, node.timeLimit); setTimeout(status_waitingformsg, node.timeLimit + 500); } // by count if( node.throttleType === "count" ) { if( isNaN(node.countLimit) || !isFinite(node.countLimit) ) { return this.error("count limit is not numeric", msg); } ++node.count; setTimeout(status_count, 0); if( node.count >= node.countLimit ) { node.send(msg); node.count = 0; setTimeout(status_sent, 0); } } // by reset else if( node.throttleType === "reset" ) { if( isNaN(node.byresetcountLimit) || !isFinite(node.byresetcountLimit) ) { return this.error("count limit is not numeric", msg); } ++node.count; if ( node.reset === false ) { setTimeout(status_count, 0); } if( ( node.count >= node.byresetcountLimit && !node.reset ) || ( !node.count >= node.byresetcountLimit && node.reset ) ) { node.reset = true; node.send(msg); setTimeout(status_sent, 0); setTimeout(status_waitingformsgreset, node.timeLimit + 501); } if( msg.reset ) { node.count = 0; node.reset = false; setTimeout(status_reset, node.timeLimit); setTimeout(status_waitingformsg, node.timeLimit + 500); } } // unknown throttle type else { this.error("unknown throttle type '" + node.throttleType + "'", msg); } }); } RED.nodes.registerType("timeframerlt", timeframerlt); };