Skip to content

Commit

Permalink
Merge pull request #108 from zwave-js/dev
Browse files Browse the repository at this point in the history
Multiple Fan-out + Throttle
  • Loading branch information
marcus-j-davies authored Sep 25, 2021
2 parents 3997087 + a43764c commit 81e1d6a
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 16 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# node-red-contrib-zwave-js Change Log


- 6.1.0

**Changes**
- The device node set to **Multiple Nodes**, now supports omitting the **node** in your payload.
The submitted payload will be distrbuted to each node, but will do so with rate limiting, which can be changed.

Including a **node** in your payload, will target that node only - providing it is selected.

- 6.0.0

**Breaking Changes**
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
{
"name": "node-red-contrib-zwave-js",
"version": "6.0.0",
"version": "6.1.0",
"license": "MIT",
"description": "An extremely powerful, easy to use, and feature rich Z-Wave node for Node Red, based on Z-Wave JS.",
"dependencies": {
"@serialport/bindings": "9.2.1",
"express": "^4.17.1",
"limiter": "^2.1.0",
"lodash": "^4.17.21",
"serialport": "9.2.1",
"winston": "^3.3.3",
Expand All @@ -14,7 +15,7 @@
},
"devDependencies": {
"eslint": "^7.32.0",
"prettier": "^2.4.0"
"prettier": "^2.4.1"
},
"engines": {
"node": ">=12.22.2",
Expand Down
1 change: 0 additions & 1 deletion zwave-js/event-filter.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
'use strict';
module.exports = function (RED) {
const LD = require('lodash');

Expand Down
2 changes: 0 additions & 2 deletions zwave-js/ui/client.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

/* eslint-env jquery */
/* eslint-env browser */
/*eslint no-undef: "warn"*/
Expand Down
1 change: 0 additions & 1 deletion zwave-js/ui/server.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
'use strict';
const express = require('express');

const _Context = {};
Expand Down
27 changes: 23 additions & 4 deletions zwave-js/zwave-device.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
filteredNodeId: { value: 'All' },
multicast: { value: false },
datamode: { value: 'Send/Receive' },
messagesPerMS: { value: 1 },
messageInterval: { value: 250 },
outputs: { value: 1 },
inputs: { value: 1 }
},
Expand Down Expand Up @@ -43,6 +45,11 @@
function SortUI() {
let node = this;

let Rate = $('#drate');
let Mode = $('#node-input-filteredMode');
let Filter = $('#node-input-filteredNodeId');
Rate.css({ display: 'none' });

// Subflow Options
const inSubflow = !!RED.nodes.subflow(node.z);
if (inSubflow) {
Expand All @@ -56,10 +63,14 @@
$('#node-input-datamode').val('Send/Receive');
}

$.getJSON('zwjsgetnodelist', (data) => {
let Mode = $('#node-input-filteredMode');
let Filter = $('#node-input-filteredNodeId');
if (this.messagesPerMS === undefined) {
$('#node-input-messagesPerMS').val(1);
}
if (this.messageInterval === undefined) {
$('#node-input-messageInterval').val(250);
}

$.getJSON('zwjsgetnodelist', (data) => {
Filter.empty();

let Locations = Object.keys(data);
Expand Down Expand Up @@ -97,6 +108,7 @@
Mode.val('Multicast');
} else {
Mode.val('Multiple');
Rate.css({ display: 'block' });
}
}

Expand Down Expand Up @@ -143,6 +155,8 @@
function SortFilterChange() {
let Mode = $('#node-input-filteredMode');
let Filter = $('#node-input-filteredNodeId');
let Rate = $('#drate');
Rate.css({ display: 'none' });

switch (Mode.val()) {
case 'All':
Expand Down Expand Up @@ -178,6 +192,7 @@
Filter.prop('disabled', false);
Filter.attr('multiple', '');
$('#node-input-multicast').prop('checked', false);
Rate.css({ display: 'block' });
break;

case 'Multicast':
Expand Down Expand Up @@ -240,6 +255,10 @@
<option value="Message">As Specified</option>
</select>
</div>
<div class="form-row" id="drate">
<label for="node-input-messagesPerMS" style="width:130px"><i class="fa fa-pencil"></i> Distribution Rate</label>
<input style="width:50px" type="text" id="node-input-messagesPerMS" placeholder="1"> node(s) / <input style="width:50px" type="text" id="node-input-messageInterval" placeholder="250"> ms
</div>
<div class="form-row">
<label for="node-input-datamode" style="width:130px"><i class="fa fa-pencil"></i> Data Mode</label>
<select id="node-input-datamode">
Expand All @@ -263,7 +282,7 @@
<tr><td colspan="2">&nbsp;</td></tr>
<tr>
<td style="width:70px;vertical-align:top"><strong>Multiple Nodes</strong></td>
<td> - Will listen for updates on the specified Nodes.<br /> - You will need to specify the <strong>node</strong>, in your outgoing payload.</td>
<td> - Will listen for updates on the specified Nodes.<br /> - Will send individual messages to each selected node.<br />- If <strong>node</strong> is specified, it will only address that node, but will continue to receive for selected nodes.</td>
</tr>
<tr><td colspan="2">&nbsp;</td></tr>
<tr>
Expand Down
58 changes: 53 additions & 5 deletions zwave-js/zwave-device.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
'use strict';
module.exports = function (RED) {
const Limiter = require('limiter');
const LD = require('lodash');
function Init(config) {
RED.nodes.createNode(this, config);
const node = this;

const LimiterSettings = {
tokensPerInterval: 1,
interval: 250
};

if (
config.messagesPerMS !== undefined &&
!isNaN(config.messagesPerMS) &&
parseInt(config.messagesPerMS) > 0
) {
if (
config.messageInterval !== undefined &&
!isNaN(config.messageInterval) &&
parseInt(config.messageInterval) > 0
) {
LimiterSettings.tokensPerInterval = parseInt(config.messagesPerMS);
LimiterSettings.interval = parseInt(config.messageInterval);
}
}

const RateLimiter = new Limiter.RateLimiter(LimiterSettings);

let Out = true;
let DynamicIDListener = -1;

Expand Down Expand Up @@ -111,7 +134,10 @@ module.exports = function (RED) {
msg.payload.node.push(parseInt(N));
});
// Multiple
} else if (Array.isArray(config.filteredNodeId)) {
} else if (
Array.isArray(config.filteredNodeId) &&
msg.payload.node !== undefined
) {
if (!config.filteredNodeId.includes(msg.payload.node.toString())) {
const ErrorMSG =
'Target node is not enabled. Please add this node to the list of nodes to listen to.';
Expand All @@ -137,9 +163,31 @@ module.exports = function (RED) {
return;
}

RED.events.emit('zwjs:node:command', msg);
if (done) {
done();
if (
msg.payload.node === undefined &&
Array.isArray(config.filteredNodeId)
) {
for (let i = 0; i < config.filteredNodeId.length; i++) {
node.status({
fill: 'yellow',
shape: 'dot',
text: 'Mode: Multiple (Throttling)'
});
await RateLimiter.removeTokens(1);
const TR = LD.cloneDeep(msg);
TR.payload.node = parseInt(config.filteredNodeId[i]);
RED.events.emit('zwjs:node:command', TR);
}
node.status({
fill: 'green',
shape: 'dot',
text: 'Mode: Multiple'
});
} else {
RED.events.emit('zwjs:node:command', msg);
if (done) {
done();
}
}
} catch (Err) {
const E = new Error(Err.message);
Expand Down

0 comments on commit 81e1d6a

Please sign in to comment.