node-red-contrib-knx-ultimate 3.0.10 → 3.1.0
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 +3 -0
- package/nodes/knxUltimate-config.js +11 -2
- package/nodes/knxUltimate.html +180 -39
- package/nodes/knxUltimate.js +55 -2
- package/nodes/knxUltimateAutoResponder.html +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
# CHANGELOG
|
|
8
8
|
|
|
9
|
+
**Version 3.1.0** - August 2024<br/>
|
|
10
|
+
- NEW: KNX Function code editor in the device node: you can now write you own script to handle inbound and outboud KNX messages.<br/>
|
|
11
|
+
|
|
9
12
|
**Version 3.0.10** - August 2024<br/>
|
|
10
13
|
- Warning: Node-Red version **equals or major than 3.1.1** is needed to run this node.<br/>
|
|
11
14
|
- KNX Auto Responder node (BETA): fixed issue with unused saved values. Please be aware that until the node exits beta, there can be breaking changes.<br/>
|
|
@@ -107,7 +107,7 @@ module.exports = (RED) => {
|
|
|
107
107
|
// 15/12/2021
|
|
108
108
|
|
|
109
109
|
// 05/12/2021 Set the protocol (this is undefined if coming from ild versions
|
|
110
|
-
if (
|
|
110
|
+
if (node.hostProtocol === "Auto") {
|
|
111
111
|
// Auto set protocol based on IP
|
|
112
112
|
if (
|
|
113
113
|
node.host.startsWith("224.") ||
|
|
@@ -790,8 +790,17 @@ module.exports = (RED) => {
|
|
|
790
790
|
// 04/04/2021 Supergiovane: save value to node.exposedGAs
|
|
791
791
|
if (typeof _dest === "string" && _rawValue !== undefined && (_evt === "GroupValue_Write" || _evt === "GroupValue_Response")) {
|
|
792
792
|
try {
|
|
793
|
+
const ret = { ga: _dest, rawValue: _rawValue, dpt: undefined, devicename: undefined };
|
|
793
794
|
node.exposedGAs = node.exposedGAs.filter((item) => item.ga !== _dest); // Remove previous
|
|
794
|
-
node.
|
|
795
|
+
if (node.csv !== undefined && node.csv !== '' && node.csv.length !== 0) {
|
|
796
|
+
// Add the dpt
|
|
797
|
+
const found = node.csv.find(a => a.ga === _dest);
|
|
798
|
+
if (found !== undefined) {
|
|
799
|
+
ret.dpt = found.dpt;
|
|
800
|
+
ret.devicename = found.devicename;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
node.exposedGAs.push(ret); // add the new
|
|
795
804
|
} catch (error) { }
|
|
796
805
|
}
|
|
797
806
|
|
package/nodes/knxUltimate.html
CHANGED
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
formatmultiplyvalue: { value: 1 },
|
|
29
29
|
formatnegativevalue: { value: "leave" },
|
|
30
30
|
formatdecimalsvalue: { value: 999 },
|
|
31
|
-
passthrough: { value: "no" }
|
|
31
|
+
passthrough: { value: "no" },
|
|
32
|
+
outputFunctionCode: { value: "" },
|
|
33
|
+
inputFunctionCode: { value: "" }
|
|
32
34
|
},
|
|
33
35
|
inputs: 1,
|
|
34
36
|
outputs: 1,
|
|
@@ -57,8 +59,6 @@
|
|
|
57
59
|
var oNodeServer = RED.nodes.node($("#node-input-server").val()); // Store the config-node
|
|
58
60
|
$("#tabs").tabs();
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
62
|
// 15/09/2020 Supergiovane, set the help sample based on Datapoint
|
|
63
63
|
function knxUltimateDptsGetHelp(_dpt, _forceClose) {
|
|
64
64
|
if ($("#node-input-server").val() !== "_ADD_" && $("#node-input-server").val() !== '' && _dpt !== null && _dpt !== '') {
|
|
@@ -76,7 +76,7 @@
|
|
|
76
76
|
id: 'example-editor',
|
|
77
77
|
mode: 'ace/mode/javascript',
|
|
78
78
|
value: data.help//this.exampleText
|
|
79
|
-
})
|
|
79
|
+
})//.renderer.setShowGutter(false);//A.setReadOnly(true).setShowPrintMargin(false);
|
|
80
80
|
if (data.helplink !== "") $("#sampleCodeEditor").html(" <i class=\"fa fa-question-circle\"></i> <a target=\"_blank\" href=\"" + data.helplink + "\"><u>Link example of " + _dpt + "</u></a>");
|
|
81
81
|
} else {
|
|
82
82
|
// No help avaiable
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
id: 'example-editor',
|
|
85
85
|
mode: 'ace/mode/javascript',
|
|
86
86
|
value: "Currently, no sample payload is avaiable, sorry."
|
|
87
|
-
})
|
|
87
|
+
})//.renderer.setShowGutter(false);//B.setReadOnly(true).setShowPrintMargin(false);
|
|
88
88
|
if (data.helplink !== "") $("#sampleCodeEditor").html(" <i class=\"fa fa-question-circle\"></i> <a target=\"_blank\" href=\"" + data.helplink + "\"><u>Link to wiki</u></a>");
|
|
89
89
|
}
|
|
90
90
|
} catch (error) {
|
|
@@ -93,6 +93,63 @@
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
node.outputFunctionCodeEditor = RED.editor.createEditor({
|
|
97
|
+
id: 'outputFunctionCode-editor',
|
|
98
|
+
mode: 'ace/mode/nrjavascript',
|
|
99
|
+
value: node.outputFunctionCode
|
|
100
|
+
});
|
|
101
|
+
node.inputFunctionCodeEditor = RED.editor.createEditor({
|
|
102
|
+
id: 'inputFunctionCode-editor',
|
|
103
|
+
mode: 'ace/mode/nrjavascript',
|
|
104
|
+
value: node.inputFunctionCode
|
|
105
|
+
});
|
|
106
|
+
// Snippets
|
|
107
|
+
$("#snippetOne").on("click", function (event) {
|
|
108
|
+
node.outputFunctionCodeEditor.session.setValue(`// @ts-nocheck
|
|
109
|
+
// Replace 'x/x/x' with the real status group address.
|
|
110
|
+
const statusGA = getGAValue('x/x/x','1.001');
|
|
111
|
+
if (msg.payload !== statusGA){ // " !==" means " not equal"
|
|
112
|
+
return msg;
|
|
113
|
+
}else{
|
|
114
|
+
// Both values are identical, so i don't send the msg.
|
|
115
|
+
return;
|
|
116
|
+
}`);
|
|
117
|
+
});
|
|
118
|
+
$("#snippetTwo").on("click", function (event) {
|
|
119
|
+
node.inputFunctionCodeEditor.session.setValue(`// This is a sample of the msg received from the KNX BUS
|
|
120
|
+
const inputMSG = {
|
|
121
|
+
topic: '0/0/10',
|
|
122
|
+
devicename: 'Plafoniera soggiorno [switch]',
|
|
123
|
+
payload: false,
|
|
124
|
+
payloadmeasureunit: 'unknown',
|
|
125
|
+
payloadsubtypevalue: 'Off',
|
|
126
|
+
gainfo: {
|
|
127
|
+
maingroupname: 'Attuatori luci',
|
|
128
|
+
middlegroupname: 'Luci primo piano',
|
|
129
|
+
ganame: 'Plafoniera soggiorno [switch]',
|
|
130
|
+
maingroupnumber: '0',
|
|
131
|
+
middlegroupnumber: '0',
|
|
132
|
+
ganumber: '10'
|
|
133
|
+
},
|
|
134
|
+
knx: {
|
|
135
|
+
event: 'GroupValue_Write',
|
|
136
|
+
dpt: '1.001',
|
|
137
|
+
dptdesc: 'Switch',
|
|
138
|
+
source: '15.15.22',
|
|
139
|
+
destination: '0/0/10',
|
|
140
|
+
rawValue: 'bufferValue'
|
|
141
|
+
},
|
|
142
|
+
previouspayload: false
|
|
143
|
+
}
|
|
144
|
+
return msg`);
|
|
145
|
+
});
|
|
146
|
+
$("#snippetThree").on("click", function (event) {
|
|
147
|
+
node.inputFunctionCodeEditor.session.setValue(`// @ts-nocheck
|
|
148
|
+
// The current msg contains the internal temperature in the "msg.payload" property, but we want to emit the external temperature as well.
|
|
149
|
+
msg.externalTemperature = getGAValue('0/0/10'); // In case the ETS file is missing, you must specify the dpt as well: getGAValue('0/0/10','9.001')
|
|
150
|
+
return msg;`);
|
|
151
|
+
});
|
|
152
|
+
|
|
96
153
|
function checkUI() {
|
|
97
154
|
|
|
98
155
|
// Backward compatibility
|
|
@@ -352,7 +409,8 @@
|
|
|
352
409
|
},
|
|
353
410
|
oneditsave: function () {
|
|
354
411
|
var node = this;
|
|
355
|
-
|
|
412
|
+
this.outputFunctionCode = this.outputFunctionCodeEditor.getValue();
|
|
413
|
+
this.inputFunctionCode = this.inputFunctionCodeEditor.getValue();
|
|
356
414
|
//this.propertyType = $("#node-input-property").typedInput('type');
|
|
357
415
|
|
|
358
416
|
// 19/02/2020 Warn user that the node will node encode/decode datagram, if Listen All GA's if the config node doesn't contain the csv
|
|
@@ -378,14 +436,18 @@
|
|
|
378
436
|
// $("#GAandDPT").show()
|
|
379
437
|
// $("#divOutputRBE").show()
|
|
380
438
|
// $("#divInputRBE").show()
|
|
381
|
-
|
|
439
|
+
//$("#helpallga").show()
|
|
382
440
|
}
|
|
383
441
|
|
|
384
442
|
// 15/09/2020 Supergiovane, Detele the sample help editor
|
|
385
443
|
try {
|
|
386
444
|
node.sampleEditor.destroy();
|
|
387
|
-
RED.editor.destroy(); // 23/01/2024 added
|
|
388
445
|
delete node.sampleEditor;
|
|
446
|
+
node.outputFunctionCodeEditor.destroy();
|
|
447
|
+
delete node.outputFunctionCodeEditor;
|
|
448
|
+
node.inputFunctionCodeEditor.destroy();
|
|
449
|
+
delete node.inputFunctionCodeEditor;
|
|
450
|
+
//RED.editor.destroy(); // 23/01/2024 added
|
|
389
451
|
} catch (error) { }
|
|
390
452
|
|
|
391
453
|
},
|
|
@@ -393,8 +455,12 @@
|
|
|
393
455
|
// 15/09/2020 Supergiovane, Detele the sample help editor
|
|
394
456
|
try {
|
|
395
457
|
node.sampleEditor.destroy();
|
|
396
|
-
RED.editor.destroy(); // 23/01/2024 added
|
|
397
458
|
delete node.sampleEditor;
|
|
459
|
+
node.outputFunctionCodeEditor.destroy();
|
|
460
|
+
delete node.outputFunctionCodeEditor;
|
|
461
|
+
node.inputFunctionCodeEditor.destroy();
|
|
462
|
+
delete node.inputFunctionCodeEditor;
|
|
463
|
+
RED.editor.destroy(); // 23/01/2024 added
|
|
398
464
|
} catch (error) { }
|
|
399
465
|
}
|
|
400
466
|
})
|
|
@@ -486,19 +552,17 @@
|
|
|
486
552
|
</label>
|
|
487
553
|
<!-- <div id="helpallga">Some Content Here</div> -->
|
|
488
554
|
</div>
|
|
489
|
-
|
|
490
|
-
|
|
491
555
|
<div id="tabs">
|
|
492
556
|
<ul>
|
|
493
557
|
<li><a href="#tabs-1"><i class="fa fa-braille"></i> Advanced options</a></li>
|
|
494
|
-
<li><a href="#tabs-2"><i class="fa fa-
|
|
495
|
-
<li><a href="#tabs-3"><i class="fa fa-
|
|
558
|
+
<li><a href="#tabs-2"><i class="fa fa-code"></i> KNX Function (BETA)</a></li>
|
|
559
|
+
<li><a href="#tabs-3"><i class="fa fa-medkit"></i> Payload Sample</a></li>
|
|
496
560
|
</ul>
|
|
497
561
|
<div id="tabs-1">
|
|
498
562
|
<div class="form-row" style="padding:10px">
|
|
499
563
|
<div class="form-row">
|
|
500
564
|
<dt>
|
|
501
|
-
<i class="fa fa-arrow-right"></i
|
|
565
|
+
<i class="fa fa-arrow-right"></i>| SEND msg to KNX BUS
|
|
502
566
|
</dt>
|
|
503
567
|
</div>
|
|
504
568
|
<div class="form-row">
|
|
@@ -521,7 +585,7 @@
|
|
|
521
585
|
<option value="false">Disable</option>
|
|
522
586
|
</select>
|
|
523
587
|
</div>
|
|
524
|
-
<
|
|
588
|
+
<hr>
|
|
525
589
|
<div class="form-row">
|
|
526
590
|
<dt>
|
|
527
591
|
|<i class="fa fa-arrow-right"></i> RECEIVE msg from KNX BUS
|
|
@@ -569,7 +633,6 @@
|
|
|
569
633
|
<i class="fa fa-sign-in"></i> React to read telegrams
|
|
570
634
|
</label>
|
|
571
635
|
</div>
|
|
572
|
-
|
|
573
636
|
<div id="divnotifyreadrequestautoreact">
|
|
574
637
|
<dd>
|
|
575
638
|
<div class="form-row">
|
|
@@ -591,23 +654,17 @@
|
|
|
591
654
|
</div>
|
|
592
655
|
</dd>
|
|
593
656
|
</div>
|
|
594
|
-
</div>
|
|
595
|
-
</div>
|
|
596
|
-
|
|
597
|
-
<div id="tabs-2">
|
|
598
|
-
<div class="form-row" style="padding:10px">
|
|
599
657
|
<div class="form-row">
|
|
600
658
|
<dt>
|
|
601
659
|
<i class="fa fa-sort-numeric-asc"></i> Format numeric values coming from the KNX BUS
|
|
602
660
|
</dt>
|
|
603
661
|
</div>
|
|
604
|
-
|
|
605
662
|
<div class="form-row">
|
|
606
|
-
<label style="width:
|
|
663
|
+
<label style="width:180px" for="node-input-formatmultiplyvalue">
|
|
607
664
|
<i class="fa fa-calculator"></i>
|
|
608
665
|
<span data-i18n="knxUltimate.properties.node-input-formatmultiplyvalue"></span>
|
|
609
666
|
</label>
|
|
610
|
-
<select
|
|
667
|
+
<select id="node-input-formatmultiplyvalue">
|
|
611
668
|
<option value=1 data-i18n="knxUltimate.selectlists.Multiply_leave"></option>
|
|
612
669
|
<option value=0.001 data-i18n="knxUltimate.selectlists.Multiply_divide1000"></option>
|
|
613
670
|
<option value=0.01 data-i18n="knxUltimate.selectlists.Multiply_divide100"></option>
|
|
@@ -618,11 +675,11 @@
|
|
|
618
675
|
</select>
|
|
619
676
|
</div>
|
|
620
677
|
<div class="form-row">
|
|
621
|
-
<label style="width:
|
|
678
|
+
<label style="width:180px" for="node-input-formatdecimalsvalue">
|
|
622
679
|
<i class="fa fa-expand"></i>
|
|
623
680
|
<span data-i18n="knxUltimate.properties.node-input-formatdecimalsvalue"></span>
|
|
624
681
|
</label>
|
|
625
|
-
<select
|
|
682
|
+
<select id="node-input-formatdecimalsvalue">
|
|
626
683
|
<option value=999 data-i18n="knxUltimate.selectlists.Decimals_leave"></option>
|
|
627
684
|
<option value=0 data-i18n="knxUltimate.selectlists.Decimals_roundint"></option>
|
|
628
685
|
<option value=1 data-i18n="knxUltimate.selectlists.Decimals_round1"></option>
|
|
@@ -632,29 +689,55 @@
|
|
|
632
689
|
</select>
|
|
633
690
|
</div>
|
|
634
691
|
<div class="form-row">
|
|
635
|
-
<label style="width:
|
|
692
|
+
<label style="width:180px" for="node-input-formatnegativevalue">
|
|
636
693
|
<i class="fa fa-minus-circle"></i>
|
|
637
694
|
<span data-i18n="knxUltimate.properties.node-input-formatnegativevalue"></span>
|
|
638
695
|
</label>
|
|
639
|
-
<select
|
|
696
|
+
<select id="node-input-formatnegativevalue">
|
|
640
697
|
<option value="leave" data-i18n="knxUltimate.selectlists.Negatives_leave"></option>
|
|
641
698
|
<option value="zero" data-i18n="knxUltimate.selectlists.Negatives_zero"></option>
|
|
642
699
|
<option value="abs" data-i18n="knxUltimate.selectlists.Negatives_abs"></option>
|
|
643
700
|
</select>
|
|
644
701
|
</div>
|
|
645
702
|
</div>
|
|
703
|
+
</div>
|
|
646
704
|
|
|
705
|
+
<div id="tabs-2">
|
|
706
|
+
<div class="form-row" style="padding:10px">
|
|
707
|
+
<div class="form-row">
|
|
708
|
+
<dt>
|
|
709
|
+
<i class="fa fa-arrow-right"></i>| SEND msg to KNX BUS
|
|
710
|
+
</dt>
|
|
711
|
+
</div>
|
|
712
|
+
<div style="height:200px;min-height:150px;padding:0px;">
|
|
713
|
+
<div style="height:100%;width:100%;padding:0px;" class="node-text-editor"
|
|
714
|
+
id="outputFunctionCode-editor"></div>
|
|
715
|
+
</div>
|
|
716
|
+
<i class="fa fa-code"></i> Select a snippet to be inserted<br />
|
|
717
|
+
<button type="button" id="snippetOne" class="red-ui-button">Status GA check</button>
|
|
718
|
+
<hr>
|
|
719
|
+
<div class="form-row">
|
|
720
|
+
<dt>
|
|
721
|
+
|<i class="fa fa-arrow-right"></i> RECEIVE msg from KNX BUS
|
|
722
|
+
</dt>
|
|
723
|
+
</div>
|
|
724
|
+
<div style="height:200px;min-height:150px;padding:0px;">
|
|
725
|
+
<div style="height:100%;width:100%;padding:0px;" class="node-text-editor"
|
|
726
|
+
id="inputFunctionCode-editor"></div>
|
|
727
|
+
</div>
|
|
728
|
+
<i class="fa fa-code"></i> Select a snippet to be inserted<br />
|
|
729
|
+
<button type="button" id="snippetTwo" class="red-ui-button">Show msg constructor</button>
|
|
730
|
+
<button type="button" id="snippetThree" class="red-ui-button">Add property to msg</button>
|
|
731
|
+
|
|
732
|
+
</div>
|
|
647
733
|
</div>
|
|
734
|
+
|
|
648
735
|
<div id="tabs-3">
|
|
649
736
|
<div style="height:200px;min-height:150px;padding:0px;">
|
|
650
737
|
<div style="height:100%;width:100%;padding:0px;" class="node-text-editor" id="example-editor"></div>
|
|
651
738
|
</div>
|
|
652
739
|
</div>
|
|
653
740
|
</div>
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
741
|
</div>
|
|
659
742
|
|
|
660
743
|
<div id="divDeployFirst">
|
|
@@ -681,6 +764,8 @@
|
|
|
681
764
|
| Passthrough | If set, you can pass the input mgs to the output msg. |
|
|
682
765
|
| Universal mode (listen to all Group Addresses) | By setting this, the node will read and control ALL group addresses. |
|
|
683
766
|
|
|
767
|
+
<br/>
|
|
768
|
+
<br/>
|
|
684
769
|
|
|
685
770
|
**Advanced options**
|
|
686
771
|
|Property|Description|
|
|
@@ -694,20 +779,76 @@
|
|
|
694
779
|
| React to write telegrams | The node will react (will send a msg to the flow) each time it receives a *write* telegram from the KNX bus. Usually, you want that. |
|
|
695
780
|
| React to response telegrams | The node will react (will send a msg to the flow) each time it receives a *response* telegram from the KNX bus. Usually, you want that for particular scenarios. |
|
|
696
781
|
| React to read telegrams | The node will react (will send a msg to the flow) each time it receives a *read* telegram from the KNX bus. Usually, you want that if you're want to send a custom value to the KNX BUS. |
|
|
782
|
+
| Multiply | Multiplies or divides the payload value. Works only if the value is a number. |
|
|
783
|
+
| Decimals | Round or handle decimals in any way. Works only if the value is a number. |
|
|
784
|
+
| Negatives | Handles the negative values. Works only if the value is a number. |
|
|
785
|
+
|
|
786
|
+
<br/>
|
|
787
|
+
<br/>
|
|
697
788
|
|
|
789
|
+
**KNX Function**
|
|
698
790
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
791
|
+
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.
|
|
792
|
+
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).
|
|
793
|
+
The script is called everytime the node receives a msg from the flow or a telegram from the KNX BUS.
|
|
794
|
+
|
|
795
|
+
### SEND msg to KNX BUS
|
|
796
|
+
|
|
797
|
+
List of object and functions you can use in the code
|
|
798
|
+
|
|
799
|
+
: msg (object) : The current msg object received by the node from the flow.
|
|
800
|
+
: getGAValue (GA as string, DPT as string) : Function. Get the specified GA's value, for example '1/0/1'. **DPT** is optional if you've imported the ETS file, otherwise you must specify it, for example '1.001'.
|
|
801
|
+
: return (msg) : Mandatory `return msg;`, if you want to emit the msg to the KNX BUS. Otherwise, using `return;` will not emit any message.
|
|
802
|
+
|
|
803
|
+
In this sample, we'll send the input msg to the KNX BUS only if another GA has opposite value.
|
|
804
|
+
We'll turn on the light only if it's status GA is off, and vice versa.
|
|
805
|
+
```javascript
|
|
806
|
+
const statusGA = getGAValue('0/0/09','1.001');
|
|
807
|
+
if (msg.payload !== statusGA){ // "!==" means "not equal"
|
|
808
|
+
return msg;
|
|
809
|
+
}else{
|
|
810
|
+
// Both values are identical, so i don't send the msg.
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
### RECEIVE msg from KNX BUS
|
|
816
|
+
|
|
817
|
+
List of object and functions you can use in the code
|
|
818
|
+
|
|
819
|
+
: msg (object) : The current msg object received by the node from the KNX BUS.
|
|
820
|
+
: getGAValue (GA as string, DPT as string) : Function. Get the specified GA's value, for example '1/0/1'. **DPT** is optional if you've imported the ETS file, otherwise you must specify it, for example '1.001'.
|
|
821
|
+
: return (msg) : Mandatory `return msg;`, if you want to emit the msg to the flow. Otherwise, using `return;` will not emit any message.
|
|
822
|
+
|
|
823
|
+
In this sample, we'll emit the msg object to the flow, by appending the value of another GA to the output msg.
|
|
824
|
+
The ouput msg to the flow will have also the external temp in the property `msg.externalTemperature`
|
|
825
|
+
```javascript
|
|
826
|
+
// The current msg contains the internal temperature in the "msg.payload" property, but we want to emit the external temperature as well.
|
|
827
|
+
msg.externalTemperature = getGAValue('0/0/10'); // In case the ETS file is missing, you must specify the dpt as well: getGAValue('0/0/10','9.001')
|
|
828
|
+
return msg;
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
In this other sample, we'll not emit a msg to the flow, in case msg.payload and another GA value are both false.
|
|
832
|
+
```javascript
|
|
833
|
+
if (msg.payload === false && getGAValue('0/0/11','1.001') === false){
|
|
834
|
+
// Both false, don't emit the msg to the flow.
|
|
835
|
+
return;
|
|
836
|
+
}else{
|
|
837
|
+
// Ok, emit it.
|
|
838
|
+
return msg;
|
|
839
|
+
}
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
<br/>
|
|
843
|
+
<br/>
|
|
705
844
|
|
|
706
845
|
**Payload sample**
|
|
707
846
|
|Property|Description|
|
|
708
847
|
|--|--|
|
|
709
|
-
| Sample | This will give it a hint on what to write in
|
|
848
|
+
| 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. |
|
|
710
849
|
|
|
850
|
+
<br/>
|
|
851
|
+
<br/>
|
|
711
852
|
<br/>
|
|
712
853
|
|
|
713
854
|
### Inputs
|
package/nodes/knxUltimate.js
CHANGED
|
@@ -4,6 +4,7 @@ module.exports = function (RED) {
|
|
|
4
4
|
const _ = require('lodash');
|
|
5
5
|
const KNXUtils = require('knxultimate');
|
|
6
6
|
const payloadRounder = require('./utils/payloadManipulation');
|
|
7
|
+
const dptlib = require('knxultimate').dptlib;
|
|
7
8
|
|
|
8
9
|
function knxUltimate(config) {
|
|
9
10
|
RED.nodes.createNode(this, config);
|
|
@@ -119,7 +120,10 @@ module.exports = function (RED) {
|
|
|
119
120
|
node.inputmessage = {}; // Stores the input message to be passed through
|
|
120
121
|
node.timerTTLInputMessage = null; // The stored node.inputmessage has a ttl.
|
|
121
122
|
node.sysLogger = require('./utils/sysLogger.js').get({ loglevel: node.server.loglevel || 'error' }); // 08/04/2021 new logger to adhere to the loglevel selected in the config-window
|
|
122
|
-
|
|
123
|
+
node.outputFunctionCode = config.outputFunctionCode || undefined;
|
|
124
|
+
node.inputFunctionCode = config.inputFunctionCode || undefined;
|
|
125
|
+
if (node.outputFunctionCode === '') node.outputFunctionCode = undefined
|
|
126
|
+
if (node.inputFunctionCode === '') node.inputFunctionCode = undefined
|
|
123
127
|
|
|
124
128
|
// Check if the node has a valid dpt
|
|
125
129
|
if (node.listenallga === false) {
|
|
@@ -131,6 +135,23 @@ module.exports = function (RED) {
|
|
|
131
135
|
}
|
|
132
136
|
}
|
|
133
137
|
|
|
138
|
+
// Used in the KNX Function TAB
|
|
139
|
+
let getGAValue = function getGAValue(ga = undefined, _dpt = undefined) {
|
|
140
|
+
try {
|
|
141
|
+
if (ga === undefined) return;
|
|
142
|
+
// Is there a GA in the server's exposedGAs?
|
|
143
|
+
const found = node.server.exposedGAs.find(a => a.ga === ga);
|
|
144
|
+
if (found !== undefined) {
|
|
145
|
+
if (_dpt === undefined && found.dpt === undefined) throw new Error('No CSV file imported. Please provide the dpt manually.');
|
|
146
|
+
return dptlib.fromBuffer(found.rawValue, dptlib.resolve(_dpt || found.dpt));
|
|
147
|
+
} else {
|
|
148
|
+
throw new Error('Group Address not yet read, try later.');
|
|
149
|
+
}
|
|
150
|
+
} catch (error) {
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
134
155
|
// This function is called by the knx-ultimate config node, to output a msg.payload.
|
|
135
156
|
node.handleSend = (msg) => {
|
|
136
157
|
// 27/03/2020 can i merge the last input msg arrived, with the output?
|
|
@@ -147,7 +168,23 @@ module.exports = function (RED) {
|
|
|
147
168
|
node.inputmessage = {};
|
|
148
169
|
}
|
|
149
170
|
} catch (error) { }
|
|
150
|
-
|
|
171
|
+
|
|
172
|
+
// #region "Inject the msg to the JS code, then output msg to the flow"
|
|
173
|
+
// -+++++++++++++++++++++++++++++++++++++++++++
|
|
174
|
+
if (node.outputFunctionCode !== undefined) {
|
|
175
|
+
try {
|
|
176
|
+
let outputFunction = new Function('msg', 'getGAValue', node.outputFunctionCode)
|
|
177
|
+
msg = outputFunction(msg, getGAValue);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
RED.log.error('knxUltimate: outputFunction: node ID:' + node.id + ' ' + error.message);
|
|
180
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimate: outputFunction: node id ${node.id} ` || ' ' + error.stack);
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// -+++++++++++++++++++++++++++++++++++++++++++
|
|
185
|
+
//#endregion
|
|
186
|
+
|
|
187
|
+
if (msg !== undefined) node.send(msg);
|
|
151
188
|
};
|
|
152
189
|
|
|
153
190
|
|
|
@@ -195,6 +232,22 @@ module.exports = function (RED) {
|
|
|
195
232
|
node.inputmessage = RED.util.cloneMessage(msg); // 28/03/2020 Store the message to be passed through.
|
|
196
233
|
}
|
|
197
234
|
|
|
235
|
+
// #region "Inject the msg to the JS code, then output msg to the flow"
|
|
236
|
+
// -+++++++++++++++++++++++++++++++++++++++++++
|
|
237
|
+
if (node.inputFunctionCode !== undefined) {
|
|
238
|
+
try {
|
|
239
|
+
let inputFunction = new Function('msg', 'getGAValue', node.inputFunctionCode)
|
|
240
|
+
msg = inputFunction(msg, getGAValue);
|
|
241
|
+
if (msg === undefined) return;
|
|
242
|
+
} catch (error) {
|
|
243
|
+
RED.log.error('knxUltimate: inputFunction: node ID:' + node.id + ' ' + error.message);
|
|
244
|
+
if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`knxUltimate: inputFunction: node id ${node.id} ` || ' ' + error.stack);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// -+++++++++++++++++++++++++++++++++++++++++++
|
|
249
|
+
//#endregion
|
|
250
|
+
|
|
198
251
|
// 25/07/2019 if payload is read or the Telegram type is set to "read", do a read, otherwise, write to the bus
|
|
199
252
|
if ((msg.hasOwnProperty('readstatus') && msg.readstatus === true) || node.outputtype === 'read') {
|
|
200
253
|
// READ: Send a Read request to the bus
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
outputs: 0,
|
|
17
17
|
icon: "node-knx-icon.svg",
|
|
18
18
|
label: function () {
|
|
19
|
-
return (this.name
|
|
19
|
+
return (this.name || "KNX Auto Responder");
|
|
20
20
|
},
|
|
21
|
-
paletteLabel: "Auto Responder
|
|
21
|
+
paletteLabel: "KNX Auto Responder",
|
|
22
22
|
// button: {
|
|
23
23
|
// enabled: function() {
|
|
24
24
|
// // return whether or not the button is enabled, based on the current
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"engines": {
|
|
4
4
|
"node": ">=16.0.0"
|
|
5
5
|
},
|
|
6
|
-
"version": "3.0
|
|
6
|
+
"version": "3.1.0",
|
|
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",
|