Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added doc/example5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 18 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ A <a href="http://nodered.org" target="_new">Node-RED</a> node to throttle down
* [Install](#install)
* [Usage](#usage)
* [By Time](#by-time)
* [By Period](#by-period)
* [By Count](#by-count)
* [By Block Size](#by-block-size)
* [By Reset](#by-reset)
* [Example Flows](#example-flows)
* [Example by Time](#example-by-time)
* [Example by Period](#example-by-period)
* [Example by Count](#example-by-count)
* [Example by Block Size](#example-by-block-size)
* [Example by Reset](#example-by-reset)
Expand Down Expand Up @@ -49,6 +51,12 @@ Limits the passed through messages by a given amount of time.
**For example:** setting the node to `10 seconds` means, that only one message in ten seconds will be forwarded.


### By Period

Limits the passed through messages by a given period of time.
**For example:** setting the node to `10 seconds` means, that all messages in the first ten seconds will be forwarded.


### By Count

Limits the passed through messages by a given count.
Expand Down Expand Up @@ -81,6 +89,15 @@ Simple examples showing how to use the throttle and it's output.
```


### Example by Period

![example5.png](./doc/example5.png)

```JSON
[{"id":"8383dfd6.38029","type":"function","z":"6253524.ae0e9ac","name":"info msg","func":"msg.payload = \"injected\";\nreturn msg;","outputs":1,"noerr":0,"x":508.0994567871094,"y":194.09091186523438,"wires":[["dde88359.a1484"]]},{"id":"aa17d47e.ca3ae8","type":"throttle","z":"6253524.ae0e9ac","name":"","throttleType":"period","timeLimit":"10","timeLimitType":"seconds","periodLimit":"10","periodLimitType":"seconds","countLimit":"3","blockSize":"3","locked":false,"resend":false,"x":508.0994567871094,"y":234.09091186523438,"wires":[["dde88359.a1484"]]},{"id":"87dc94db.139918","type":"inject","z":"6253524.ae0e9ac","name":"inject","topic":"","payload":"!!! PASSED THROUGH !!!","payloadType":"str","repeat":"","crontab":"","once":false,"x":198.09945678710938,"y":214.09091186523438,"wires":[["aa17d47e.ca3ae8","8383dfd6.38029"]]},{"id":"8fbc58ea.3a7da8","type":"inject","z":"6253524.ae0e9ac","name":"reset","topic":"","payload":"reset","payloadType":"str","repeat":"","crontab":"","once":false,"x":198.09945678710938,"y":274.0909118652344,"wires":[["a3b2c4d0.c76688"]]},{"id":"a3b2c4d0.c76688","type":"function","z":"6253524.ae0e9ac","name":"reset msg","func":"msg.reset = true;\nreturn msg;","outputs":1,"noerr":0,"x":328.0994567871094,"y":274.0909118652344,"wires":[["aa17d47e.ca3ae8","dde88359.a1484"]]},{"id":"dde88359.a1484","type":"debug","z":"6253524.ae0e9ac","name":"output","active":true,"console":"false","complete":"payload","x":678.0994567871094,"y":274.0909118652344,"wires":[]}]
```


### Example by Count

![example2.png](./doc/example2.png)
Expand Down Expand Up @@ -121,4 +138,4 @@ _You like to support me?_
_You appreciate my work?_
_You use it in commercial projects?_

Feel free to make a little [donation](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FFL6VQJCUZMXC)! :wink:
Feel free to make a little [donation](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FFL6VQJCUZMXC)! :wink:
37 changes: 35 additions & 2 deletions throttle.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<label for=""><i class="fa fa-filter"></i> Throttle</label>
<select id="node-input-throttleType" style="width: 70%">
<option value="time">by time</option>
<option value="period">by period</option>
<option value="count">by count</option>
<option value="block">by block size</option>
<option value="reset">by reset</option>
Expand All @@ -17,6 +18,11 @@
<input type="text" id="node-input-timeLimit" placeholder="0" style="padding-left: 5px; width: 70%">
<input type="hidden" id="node-input-timeLimitType">
</div>
<div class="form-row throttle-limit-row hidden" id="throttle-limit-row-period">
<label for="node-input-periodLimit"><i class="fa fa-clock-o"></i> Period Limit</label>
<input type="text" id="node-input-periodLimit" placeholder="0" style="padding-left: 5px; width: 70%">
<input type="hidden" id="node-input-periodLimitType">
</div>
<div class="form-row throttle-limit-row hidden" id="throttle-limit-row-count">
<label for="node-input-countLimit"><i class="fa fa-hashtag"></i> Count Limit</label>
<input type="text" id="node-input-countLimit" placeholder="0">
Expand All @@ -30,6 +36,11 @@
<input type="checkbox" id="node-input-locked" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-locked" style="width: 70%;">Locked by default?</label>
</div>
<div class="form-row">
<label>&nbsp;</label>
<input type="checkbox" id="node-input-resend" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-resend" style="width: 70%;">Resend 'reset' messages?</label>
</div>
</script>

<script type="text/x-red" data-help-name="throttle">
Expand All @@ -38,6 +49,9 @@
<p><strong>By Time:</strong><br/>
Limits the passed through messages by a given amount of time.
For example: setting the node to <code>10 seconds</code> means, that only one message in ten seconds will be forwarded.</p>
<p><strong>By Period:</strong><br/>
Limits the passed through messages by a given time period.
For example: setting the node to <code>10 seconds</code> means, that only the messages in the first ten seconds will be forwarded.</p>
<p><strong>By Count:</strong><br/>
Limits the passed through messages by a given count.
For example: setting the node to a count of <code>5</code> means, that only every fifth message will be forwarded.</p>
Expand All @@ -47,7 +61,9 @@
For example: setting the node to a block size of <code>5</code> means, that only the first five messages will be forwarded.</p>
<p><strong>By Reset:</strong><br/>
Will only pass through a single message, when a message with <code>msg.reset</code> was received before.</p>
<p>Every other messages will be dropped!</p>
<p>Every other messages will be dropped!</p><br/>
<p>When <strong>locked by default</strong> is activated, the filter will not be activated immediately.</p>
<p>When <strong>resend 'reset' messages</strong> is activated, messages containing a <code>msg.reset</code> field will also be resended to the output port (if it matches the other filter criteria).</p>
</script>

<script type="text/javascript">
Expand All @@ -58,9 +74,12 @@
throttleType: {value:"time"},
timeLimit: {value:0,validate:RED.validators.number()},
timeLimitType: {value:"seconds"},
periodLimit: {value:0,validate:RED.validators.number()},
periodLimitType: {value:"seconds"},
countLimit: {value:0,validate:RED.validators.number()},
blockSize: {value:0,validate:RED.validators.number()},
locked: {value:false}
locked: {value:false},
resend: {value:true}
},
color:"#e6e0f8",
inputs: 1,
Expand All @@ -79,6 +98,8 @@
this.blockSize = !this.blockSize ? 0 : this.blockSize;
this.timeLimit = !this.timeLimit ? 0 : this.timeLimit;
this.timeLimitType = !this.timeLimitType ? "seconds" : this.timeLimitType;
this.periodLimit = !this.periodLimit ? 0 : this.periodLimit;
this.periodLimitType = !this.periodLimitType ? "seconds" : this.periodLimitType;

// change listener for type select
$("#node-input-throttleType").change(function() {
Expand All @@ -97,6 +118,18 @@
{value: "hours", label: "hours", hasValue: true}
]
});

// typed input for period throttle
$("#node-input-periodLimit").typedInput({
default: "seconds",
typeField: $("#node-input-periodLimitType"),
types: [
{value: "milliseconds", label: "milliseconds", hasValue: true},
{value: "seconds", label: "seconds", hasValue: true},
{value: "minutes", label: "minutes", hasValue: true},
{value: "hours", label: "hours", hasValue: true}
]
});
}
});
</script>
72 changes: 50 additions & 22 deletions throttle.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,50 @@ module.exports = function(RED) {
this.throttleType = config.throttleType || "time";
this.timeLimitType = config.timeLimitType || "seconds";
this.timeLimit = Number(config.timeLimit || 0);
this.periodLimitType = config.periodLimitType || "seconds";
this.periodLimit = Number(config.periodLimit || 0);
this.countLimit = Number(config.countLimit || 0);
this.blockSize = Number(config.blockSize || 0);
this.locked = config.locked || false;

// helpers
this.time = this.locked ? Math.floor(Date.now()) : 0;
this.count = this.locked ? 1 : 0;
this.block = this.locked ? this.blockSize + 1 : 0;
this.reset = !!this.locked;

// calculate time limit in milliseconds
if( this.timeLimitType === "hours" ) {
this.timeLimit *= 60 * 60 * 1000;
}
else if( this.timeLimitType === "minutes" ) {
this.timeLimit *= 60 * 1000;
this.resend = config.resend || false;

function initialize(locked, node) {
node.time = locked ? Math.floor(Date.now()) : 0;
node.period = locked ? 0 : Math.floor(Date.now());
node.count = locked ? 1 : 0;
node.block = locked ? node.blockSize + 1 : 0;
node.reset = !!locked;
}
else if( this.timeLimitType === "seconds" ) {
this.timeLimit *= 1000;

// Initialize the current status, based on the 'locked' property
initialize(this.locked, this);

// calculate limit in milliseconds
function getMilliSeconds(limitType, limit) {
if( limitType === "hours" ) {
return limit * 60 * 60 * 1000;
}
else if( limitType === "minutes" ) {
return limit * 60 * 1000;
}
else if( limitType === "seconds" ) {
return limit * 1000;
}
}

this.timeLimit = getMilliSeconds(this.timeLimitType, this.timeLimit);
this.periodLimit = getMilliSeconds(this.periodLimitType, this.periodLimit);

this.on("input", function(msg) {
if( msg.reset) {
initialize(false, node);

if( node.resend !== true) {
// When a 'reset' message shouldn't be resended (on the output port), just skip it ...
return;
}
}

// throttle by time
if( node.throttleType === "time" ) {
if( isNaN(node.timeLimit) || !isFinite(node.timeLimit) ) {
Expand All @@ -45,6 +67,19 @@ module.exports = function(RED) {
node.send(msg);
}
}

// throttle by period
else if( node.throttleType === "period" ) {
if( isNaN(node.periodLimit) || !isFinite(node.periodLimit) ) {
return this.error("period limit is not numeric", msg);
}

var now = Math.floor(Date.now());

if( node.period + node.periodLimit > now ) {
node.send(msg);
}
}

// throttle by count
else if( node.throttleType === "count" ) {
Expand Down Expand Up @@ -74,9 +109,6 @@ module.exports = function(RED) {
if( node.block <= node.blockSize ) {
node.send(msg);
}
else if( msg.reset ) {
node.block = 0;
}
}

// throttle by reset
Expand All @@ -85,11 +117,7 @@ module.exports = function(RED) {
node.reset = true;
node.send(msg);
}
else if( msg.reset ) {
node.reset = false;
}
}

// unknown throttle type
else {
this.error("unknown throttle type '" + node.throttleType + "'", msg);
Expand Down