node-red-contrib-knx-ultimate 3.1.5 → 3.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/README.md +4 -10
- package/img/youtube-logo.jpeg +0 -0
- package/nodes/knxUltimate.html +25 -17
- package/nodes/knxUltimate.js +89 -20
- package/package.json +1 -1
- package/resources/KNXFunctionCodeSnippets.js +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
+
**Version 3.1.6** - August 2024<br/>
|
|
10
|
+
- KNX Node: KNX Function: added "self", "toggle" and "setGAValue" function. See the help.<br/>
|
|
11
|
+
- KNX Node: KNX Function: the code runs now in async/await mode.<br/>
|
|
12
|
+
- The wiki has been revamped and will be implemented with HUE samples, in the upcoming release.<br/>
|
|
13
|
+
|
|
9
14
|
**Version 3.1.5** - August 2024<br/>
|
|
10
15
|
- KNX Node: fixed some UI glitches while switching from universal mode to 3-level group Group Address.<br/>
|
|
11
16
|
- KNX Function code editor: exited BETA.<br/>
|
package/README.md
CHANGED
|
@@ -66,17 +66,12 @@ msg.payload = {red:255, green:200, blue:30} // Put some colors in our life
|
|
|
66
66
|
|
|
67
67
|
<br/>
|
|
68
68
|
|
|
69
|
-
##
|
|
69
|
+
## YOUTUBE CHANNEL
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
<img width="200px" src="https://
|
|
73
|
-
|
|
74
|
-
* <a href="https://youtu.be/sRW5sHPnYi0" target="_blank">Lesson 02 - Working with ETS file importer<br/>
|
|
75
|
-
<img width="200px" src="https://img.youtube.com/vi/sRW5sHPnYi0/0.jpg" ></a>
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
[More to come...](https://github.com/Supergiovane/node-red-contrib-knx-ultimate)
|
|
71
|
+
<a href="https://www.youtube.com/playlist?list=PL9Yh1bjbLAYpfy1Auz6CKDfXUusgMwOQr" target="_blank"><br/>
|
|
72
|
+
<img width="200px" src="https://raw.githubusercontent.com/Supergiovane/node-red-contrib-knx-ultimate/master/img/youtube-logo.jpeg" ></a>
|
|
79
73
|
|
|
74
|
+
Please subscribe to the [Youtube channel](https://www.youtube.com/playlist?list=PL9Yh1bjbLAYpfy1Auz6CKDfXUusgMwOQr) and watch the node in action.
|
|
80
75
|
|
|
81
76
|
<br/>
|
|
82
77
|
<br/>
|
|
@@ -84,7 +79,6 @@ msg.payload = {red:255, green:200, blue:30} // Put some colors in our life
|
|
|
84
79
|
## DOCUMENTATION
|
|
85
80
|
|
|
86
81
|
* [Wiki and Help](https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki)
|
|
87
|
-
* [Youtube channel](https://www.youtube.com/playlist?list=PL9Yh1bjbLAYpfy1Auz6CKDfXUusgMwOQr)
|
|
88
82
|
* [FAQ + Troubleshoot](https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/5.-FAQ-Troubleshoot)
|
|
89
83
|
* [Security best practices](https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/SECURITY)
|
|
90
84
|
|
|
Binary file
|
package/nodes/knxUltimate.html
CHANGED
|
@@ -782,7 +782,8 @@
|
|
|
782
782
|
<br/>
|
|
783
783
|
<br/>
|
|
784
784
|
|
|
785
|
-
|
|
785
|
+
## TAB Advanced options
|
|
786
|
+
|
|
786
787
|
|Property|Description|
|
|
787
788
|
|--|--|
|
|
788
789
|
||**General properties**|
|
|
@@ -805,7 +806,7 @@
|
|
|
805
806
|
<br/>
|
|
806
807
|
<br/>
|
|
807
808
|
|
|
808
|
-
|
|
809
|
+
## TAB KNX Function
|
|
809
810
|
|
|
810
811
|
You can use Javascript to modify the behaviour of the input msg coming from the flow and the output telegram sent to the KNX bus.
|
|
811
812
|
The embedded code editor provides useful objects and functions to retrieve the value of all group addresses, both with the imported ETS file and without (specifying the datapoint).
|
|
@@ -818,15 +819,18 @@ If enabled, "f(x)" indication will be added to node's name.
|
|
|
818
819
|
|
|
819
820
|
<br/>
|
|
820
821
|
|
|
821
|
-
###
|
|
822
|
-
|
|
823
|
-
List of object and functions you can use in the code
|
|
822
|
+
### List of common object and functions you can use in the code
|
|
824
823
|
|
|
825
|
-
: msg (object) : The current msg object received by the node
|
|
826
|
-
: getGAValue (string GA
|
|
824
|
+
: msg (object) : The current msg object received by the node .
|
|
825
|
+
: getGAValue (string GA, optional string DPT) : Get the specified GA's value, for example **'1/0/1'**, or also **'1/0/1 Bed table light'** (All text after a blank space will be ignored by the function. This is useful if you want to add the GA name as a reminder. With the ETS file imported, you can also copy and paste the GA and GA Name directly from the **Search GA** field.). **DPT** is optional if you've imported the ETS file, otherwise you must specify it, for example '1.001'.
|
|
826
|
+
: setGAValue (string GA, any value, optional string DPT) : Set the specified GA's value. The GA con be wrote for example **'1/0/1'**, or also **'1/0/1 Bed table light'** (All text after a blank space will be ignored by the function. This is useful if you want to add the GA name as a reminder. With the ETS file imported, you can also copy and paste the GA and GA Name directly from the **Search GA** field.). The **value** is mandatory, can be a boolean or number or string, **DPT** is optional if you've imported the ETS file, otherwise you must specify it, for example '1.001'.
|
|
827
|
+
: self (any value) : Set the currend node's value and sends the value to the KNX BUS as well. For example, *self(false)*. Caution using **self** function in the *From KNX BUS to node's OUTPUT PIN* code, because the code will be executed everytime a KNX telegram is received, so you coud have recurrency loops.
|
|
828
|
+
: toggle (nothing) : Toggle the currend node's value and sends the value to the KNX BUS as well. For example, *toggle()*. Caution using **toggle** function in the *From KNX BUS to node's OUTPUT PIN* code, because the code will be executed everytime a KNX telegram is received, so you coud have recurrency loops.
|
|
827
829
|
: node (object) : The node object.
|
|
828
830
|
: RED (Node-Red object) : The Node-Red's RED object.
|
|
829
|
-
: return (msg) : Mandatory `return msg;`, if you want to emit the
|
|
831
|
+
: return (msg) : Mandatory `return msg;`, if you want to emit the message. Otherwise, using `return;` will not emit any message.
|
|
832
|
+
|
|
833
|
+
### From KNX BUS to node's OUTPUT PIN
|
|
830
834
|
|
|
831
835
|
In this sample, we'll send the input msg to the KNX BUS only if another GA has opposite value.
|
|
832
836
|
We'll turn on the light only if it's status GA is off, and vice versa.
|
|
@@ -840,15 +844,18 @@ if (msg.payload !== statusGA){ // "!==" means "not equal"
|
|
|
840
844
|
}
|
|
841
845
|
```
|
|
842
846
|
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
847
|
+
Here, if someone switches on the light, we turn on another light 0/1/8 and after 2 seconds we switch off the lamp connected to the node.
|
|
848
|
+
```javascript
|
|
849
|
+
if (msg.payload){
|
|
850
|
+
setGAValue('0/1/8',true)
|
|
851
|
+
setTimeout(function() {
|
|
852
|
+
self(off);
|
|
853
|
+
}, 2000);
|
|
854
|
+
}
|
|
855
|
+
return msg;
|
|
856
|
+
```
|
|
846
857
|
|
|
847
|
-
|
|
848
|
-
: getGAValue (string GA , optional string DPT) : The function to get the specified GA's value, for example **'1/0/1'**, or also **'1/0/1 Bed table light'** (All text after a blank space will be ignored by the function. This is useful if you want to add the GA name as a reminder. With the ETS file imported, you can also copy and paste the GA and GA Name directly from the **Search GA** field.). **DPT** is optional if you've imported the ETS file, otherwise you must specify it, for example '1.001'.
|
|
849
|
-
: node (object) : The node object.
|
|
850
|
-
: RED (Node-Red object) : The Node-Red's RED object.
|
|
851
|
-
: return (msg) : Mandatory `return msg;`, if you want to emit the msg to the flow. Otherwise, using `return;` will not emit any message.
|
|
858
|
+
### From KNX BUS to node's ouput PIN
|
|
852
859
|
|
|
853
860
|
In this sample, we'll emit the msg object to the flow, by appending the value of another GA to the output msg.
|
|
854
861
|
The ouput msg to the flow will have also the external temp in the property `msg.externalTemperature`
|
|
@@ -872,7 +879,8 @@ if (msg.payload === false && getGAValue('0/0/11','1.001') === false){
|
|
|
872
879
|
<br/>
|
|
873
880
|
<br/>
|
|
874
881
|
|
|
875
|
-
|
|
882
|
+
## TAB Payload sample
|
|
883
|
+
|
|
876
884
|
|Property|Description|
|
|
877
885
|
|--|--|
|
|
878
886
|
| Sample | This will give it a hint on what to write in an external function node, if you want to control the node via a Node-Red function node. |
|
package/nodes/knxUltimate.js
CHANGED
|
@@ -146,13 +146,76 @@ module.exports = function (RED) {
|
|
|
146
146
|
// Is there a GA in the server's exposedGAs?
|
|
147
147
|
const found = node.server.exposedGAs.find(a => a.ga === _ga);
|
|
148
148
|
if (found !== undefined) {
|
|
149
|
-
if (_dpt === undefined && found.dpt === undefined)
|
|
149
|
+
if (_dpt === undefined && found.dpt === undefined) {
|
|
150
|
+
const errM = 'knxUltimate: getGaValue: node ID:' + node.id + ' ' + 'No CSV file imported. Please provide the dpt manually';
|
|
151
|
+
RED.log.error(errM);
|
|
152
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(errM);
|
|
153
|
+
return;
|
|
154
|
+
};
|
|
150
155
|
return dptlib.fromBuffer(found.rawValue, dptlib.resolve(_dpt || found.dpt));
|
|
151
156
|
} else {
|
|
152
|
-
|
|
157
|
+
const errM = 'knxUltimate: getGaValue: node ID:' + node.id + ' ' + 'Group Address not yet read, try later.';
|
|
158
|
+
RED.log.error(errM);
|
|
159
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(errM);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
} catch (error) {
|
|
163
|
+
const errM = 'knxUltimate: getGaValue: node ID:' + node.id + ' ' + error.stack;
|
|
164
|
+
RED.log.error(errM);
|
|
165
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(errM);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
// Used in the KNX Function TAB
|
|
169
|
+
let setGAValue = function setGAValue(_ga = undefined, _value = undefined, _dpt = undefined) {
|
|
170
|
+
try {
|
|
171
|
+
if (_ga === undefined) return;
|
|
172
|
+
// The GA can have the devicename as well, separated by a blank space (1/1/0 light table ovest),
|
|
173
|
+
// I must take the GA only
|
|
174
|
+
const blankSpacePosition = _ga.indexOf(" ");
|
|
175
|
+
if (blankSpacePosition > -1) _ga = _ga.substring(0, blankSpacePosition);
|
|
176
|
+
if (_dpt === undefined) {
|
|
177
|
+
// Try getting dpt from ETS CSV
|
|
178
|
+
const found = node.server.exposedGAs.find(a => a.ga === _ga);
|
|
179
|
+
if (found === undefined || found.dpt === undefined) {
|
|
180
|
+
const errM = 'knxUltimate: setGAValue: node ID:' + node.id + ' ' + 'No CSV file imported. Please provide the dpt manually';
|
|
181
|
+
RED.log.error(errM);
|
|
182
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(errM);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
153
185
|
}
|
|
186
|
+
node.server.writeQueueAdd({
|
|
187
|
+
grpaddr: _ga, payload: _value, dpt: _dpt, outputtype: 'write', nodecallerid: node.id,
|
|
188
|
+
});
|
|
189
|
+
} catch (error) {
|
|
190
|
+
const errM = 'knxUltimate: setGAValue: node ID:' + node.id + ' ' + error.stack;
|
|
191
|
+
RED.log.error(errM);
|
|
192
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(errM);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Used in the KNX Function TAB
|
|
196
|
+
let self = function self(_value) {
|
|
197
|
+
try {
|
|
198
|
+
node.server.writeQueueAdd({
|
|
199
|
+
grpaddr: node.topic, payload: _value, dpt: node.dpt, outputtype: 'write', nodecallerid: node.id,
|
|
200
|
+
});
|
|
154
201
|
} catch (error) {
|
|
155
|
-
|
|
202
|
+
const errM = 'knxUltimate: self: node ID:' + node.id + ' ' + error.stack;
|
|
203
|
+
RED.log.error(errM);
|
|
204
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(errM);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
// Used in the KNX Function TAB
|
|
208
|
+
let toggle = function toggle() {
|
|
209
|
+
if (node.currentPayload === true || node.currentPayload === false) {
|
|
210
|
+
try {
|
|
211
|
+
node.server.writeQueueAdd({
|
|
212
|
+
grpaddr: node.topic, payload: !node.currentPayload, dpt: node.dpt, outputtype: 'write', nodecallerid: node.id,
|
|
213
|
+
});
|
|
214
|
+
} catch (error) {
|
|
215
|
+
const errM = 'knxUltimate: toggle: node ID:' + node.id + ' ' + error.stack;
|
|
216
|
+
RED.log.error(errM);
|
|
217
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(errM);
|
|
218
|
+
}
|
|
156
219
|
}
|
|
157
220
|
}
|
|
158
221
|
|
|
@@ -176,14 +239,16 @@ module.exports = function (RED) {
|
|
|
176
239
|
// #region "Inject the msg to the JS code, then output msg to the flow"
|
|
177
240
|
// -+++++++++++++++++++++++++++++++++++++++++++
|
|
178
241
|
if (node.receiveMsgFromKNXCode !== undefined) {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
242
|
+
(async () => {
|
|
243
|
+
try {
|
|
244
|
+
let receiveMsgFromKNXCode = new Function('msg', 'getGAValue', 'node', 'RED', 'self', 'toggle', 'setGAValue', node.receiveMsgFromKNXCode)
|
|
245
|
+
msg = await receiveMsgFromKNXCode(msg, getGAValue, node, RED, self, toggle, setGAValue);
|
|
246
|
+
} catch (error) {
|
|
247
|
+
RED.log.error('knxUltimate: receiveMsgFromKNXCode: node ID:' + node.id + ' ' + error.message);
|
|
248
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimate: receiveMsgFromKNXCode: node id ${node.id} ` || ' ' + error.stack);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
})();
|
|
187
252
|
}
|
|
188
253
|
// -+++++++++++++++++++++++++++++++++++++++++++
|
|
189
254
|
//#endregion
|
|
@@ -239,19 +304,23 @@ module.exports = function (RED) {
|
|
|
239
304
|
// #region "Inject the msg to the JS code, then output msg to the flow"
|
|
240
305
|
// -+++++++++++++++++++++++++++++++++++++++++++
|
|
241
306
|
if (node.sendMsgToKNXCode !== undefined) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
307
|
+
(async () => {
|
|
308
|
+
try {
|
|
309
|
+
let sendMsgToKNXCode = new Function('msg', 'getGAValue', 'node', 'RED', 'self', 'toggle', 'setGAValue', node.sendMsgToKNXCode)
|
|
310
|
+
msg = await sendMsgToKNXCode(msg, getGAValue, node, RED, self, toggle, setGAValue);
|
|
311
|
+
if (msg === undefined) return;
|
|
312
|
+
} catch (error) {
|
|
313
|
+
RED.log.error('knxUltimate: sendMsgToKNXCode: node ID:' + node.id + ' ' + error.message);
|
|
314
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimate: sendMsgToKNXCode: node id ${node.id} ` || ' ' + error.stack);
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
})();
|
|
251
318
|
}
|
|
252
319
|
// -+++++++++++++++++++++++++++++++++++++++++++
|
|
253
320
|
//#endregion
|
|
254
321
|
|
|
322
|
+
|
|
323
|
+
|
|
255
324
|
// 25/07/2019 if payload is read or the Telegram type is set to "read", do a read, otherwise, write to the bus
|
|
256
325
|
if ((msg.hasOwnProperty('readstatus') && msg.readstatus === true) || node.outputtype === 'read') {
|
|
257
326
|
// READ: Send a Read request to the bus
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=16.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "3.1.
|
|
6
|
+
"version": "3.1.6",
|
|
7
7
|
"description": "Control your KNX intallation via Node-Red! A bunch of KNX nodes, with integrated Philips HUE control and ETS group address importer. Easy to use and highly configurable.",
|
|
8
8
|
"dependencies": {
|
|
9
9
|
"binary-parser": "2.2.1",
|
|
@@ -6,7 +6,8 @@ const statusGA = getGAValue('x/x/x','1.001');
|
|
|
6
6
|
if (msg.payload !== statusGA){ // " !==" means " not equal"
|
|
7
7
|
return msg;
|
|
8
8
|
}else{
|
|
9
|
-
// Both values are identical, so i don't send the msg.
|
|
9
|
+
// Both values are identical, so i don't send the msg.
|
|
10
|
+
node.status({fill:"grey",shape:"dot",text:"Not sent"});
|
|
10
11
|
return;
|
|
11
12
|
}`;
|
|
12
13
|
|