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 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
- ## LESSONS FROM BEGINNER TO CERTIFIED KNX-ULTIMATE GURU STATUS
69
+ ## YOUTUBE CHANNEL
70
70
 
71
- * <a href="https://youtu.be/4rjrMqszhP8" target="_blank">Lesson 01 - Introduction to KNX Device<br/>
72
- <img width="200px" src="https://img.youtube.com/vi/4rjrMqszhP8/0.jpg" ></a>
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
@@ -782,7 +782,8 @@
782
782
  <br/>
783
783
  <br/>
784
784
 
785
- **Advanced options**
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
- **KNX Function**
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
- ### From KNX BUS to node's OUTPUT PIN
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 from the flow.
826
- : 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'.
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 msg to the KNX BUS. Otherwise, using `return;` will not emit any message.
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
- ### From KNX BUS to node's ouput PIN
844
-
845
- List of object and functions you can use in the code
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
- : msg (object) : The current msg object received by the node from the KNX BUS.
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
- **Payload sample**
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. |
@@ -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) throw new Error('No CSV file imported. Please provide the dpt manually.');
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
- throw new Error('Group Address not yet read, try later.');
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
- throw error;
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
- try {
180
- let receiveMsgFromKNXCode = new Function('msg', 'getGAValue', 'node', 'RED', node.receiveMsgFromKNXCode)
181
- msg = receiveMsgFromKNXCode(msg, getGAValue, node, RED);
182
- } catch (error) {
183
- RED.log.error('knxUltimate: receiveMsgFromKNXCode: node ID:' + node.id + ' ' + error.message);
184
- if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimate: receiveMsgFromKNXCode: node id ${node.id} ` || ' ' + error.stack);
185
- return;
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
- try {
243
- let sendMsgToKNXCode = new Function('msg', 'getGAValue', 'node', 'RED', node.sendMsgToKNXCode)
244
- msg = sendMsgToKNXCode(msg, getGAValue, node, RED);
245
- if (msg === undefined) return;
246
- } catch (error) {
247
- RED.log.error('knxUltimate: sendMsgToKNXCode: node ID:' + node.id + ' ' + error.message);
248
- if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimate: sendMsgToKNXCode: node id ${node.id} ` || ' ' + error.stack);
249
- return;
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.5",
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