node-red-contrib-knx-ultimate 2.5.1 → 3.0.0-beta2
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/.eslintrc.json +3 -2
- package/CHANGELOG.md +13 -0
- package/README.md +2 -1
- package/{KNXEngine → _JS_KNXEngine}/README.md +7 -7
- package/{KNXEngine → _JS_KNXEngine}/index.js +1 -1
- package/{KNXEngine → _JS_KNXEngine}/sample.js +5 -5
- package/{KNXEngine → _JS_KNXEngine}/sampleSecure.js +1 -1
- package/{KNXEngine → _JS_KNXEngine}/src/KNXClient.js +3 -3
- package/_JS_KNXEngine/src/dptlib/dpt60002.js +101 -0
- package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectResponse.js +2 -0
- package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConstants.js +1 -0
- package/nodes/commonFunctions.js +3 -3
- package/nodes/hue-config.html +2 -0
- package/nodes/hue-config.js +8 -0
- package/nodes/knxUltimate-config.html +2 -0
- package/nodes/knxUltimate-config.js +226 -223
- package/nodes/knxUltimate.html +124 -57
- package/nodes/knxUltimate.js +100 -60
- package/nodes/knxUltimateAlerter.html +7 -12
- package/nodes/knxUltimateAlerter.js +3 -2
- package/nodes/knxUltimateGarageDoorBarrierOpener.html +7 -12
- package/nodes/knxUltimateGarageDoorBarrierOpener.js +2 -2
- package/nodes/knxUltimateGlobalContext.html +2 -0
- package/nodes/knxUltimateHueBattery.html +11 -14
- package/nodes/knxUltimateHueButton.html +27 -22
- package/nodes/knxUltimateHueButton.js +1 -1
- package/nodes/knxUltimateHueContactSensor.html +12 -8
- package/nodes/knxUltimateHueLight.html +17 -24
- package/nodes/knxUltimateHueLight.js +1 -2
- package/nodes/knxUltimateHueLightSensor.html +11 -14
- package/nodes/knxUltimateHueMotion.html +11 -14
- package/nodes/knxUltimateHueScene.html +24 -19
- package/nodes/knxUltimateHueScene.js +2 -1
- package/nodes/knxUltimateHueTapDial.html +11 -14
- package/nodes/knxUltimateHueTemperatureSensor.html +11 -14
- package/nodes/knxUltimateHueZigbeeConnectivity.html +11 -14
- package/nodes/knxUltimateHuedevice_software_update.html +261 -0
- package/nodes/knxUltimateHuedevice_software_update.js +134 -0
- package/nodes/knxUltimateLoadControl.html +4 -11
- package/nodes/knxUltimateLoadControl.js +1 -1
- package/nodes/knxUltimateLogger.html +3 -1
- package/nodes/knxUltimateSceneController.html +14 -15
- package/nodes/knxUltimateViewer.html +2 -0
- package/nodes/knxUltimateViewer.js +1 -1
- package/nodes/knxUltimateWatchDog.html +3 -1
- package/nodes/utils/payloadManipulation.js +49 -1
- package/nodes/utils/utils.js +4 -0
- package/package.json +6 -4
- package/resources/htmlUtils.js +27 -0
- /package/{KNXEngine → _JS_KNXEngine}/CHANGELOG.md +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/LICENSE +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/dpt 2.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/dpt.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/logo 2.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/logo-big 2.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/logo-big.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/logo.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/nodered 2.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/img/nodered.png +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/package.json +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/simpleSample.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/Curve25519.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/KNXSocketOptions.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/KNXsecureKeyring.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/KnxLog.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/cur.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt1.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt10.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt11.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt12.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt13.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt14.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt15.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt16.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt17.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt18.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt19.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt2.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt20.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt21.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt213.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt22.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt222.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt232.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt235.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt237.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt238.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt242.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt249.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt251.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt275.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt28.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt29.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt3.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt4.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt5.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt6.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt60001.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt7.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt8.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt9.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt999.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/index.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/BufferLengthError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/DateFormatError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/DuplicateRequestError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/InvalidValueError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/NotImplementedError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/RequestTimeoutError.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/errors/index.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/index.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/CRD.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/CRI.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/CRIFactory.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/DIB.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/DeviceInfo.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/HPAI.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/IPConfig.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/IPCurrentConfig.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXAddress.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXAddresses.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectionStateRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectionStateResponse.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDataBuffer.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDescriptionRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDescriptionResponse.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDisconnectRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDisconnectResponse.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXHeader.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXPacket.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXProtocol.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXRoutingIndication.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXSearchRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXSearchResponse.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXSecureSessionRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXTunnelingAck.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXTunnelingRequest.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXUtils.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/ServiceFamilies.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/TunnelCRI.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/AdditionalInfo.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/CEMIConstants.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/CEMIFactory.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/CEMIMessage.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/ControlField.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/LDataCon.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/LDataInd.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/LDataReq.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/NPDU.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/TLVInfo.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/protocol/index.js +0 -0
- /package/{KNXEngine → _JS_KNXEngine}/src/util/ipAddressHelper.js +0 -0
package/nodes/knxUltimate.html
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<!-- <script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/jquery.searchableSelect.js"></script> -->
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/htmlUtils.js"></script>
|
|
5
|
+
|
|
4
6
|
<script type="text/javascript">
|
|
5
7
|
RED.nodes.registerType('knxUltimate', {
|
|
6
8
|
category: "KNX Ultimate",
|
|
@@ -9,6 +11,7 @@
|
|
|
9
11
|
//buttonState: {value: true},
|
|
10
12
|
server: { type: "knxUltimate-config", required: true },
|
|
11
13
|
topic: { value: "" },
|
|
14
|
+
setTopicType: { value: "str" },
|
|
12
15
|
outputtopic: { value: "" },
|
|
13
16
|
dpt: { value: "" },
|
|
14
17
|
initialread: { value: 0 },
|
|
@@ -31,7 +34,7 @@
|
|
|
31
34
|
outputs: 1,
|
|
32
35
|
icon: "node-knx-icon.svg",
|
|
33
36
|
label: function () {
|
|
34
|
-
return ((this.outputRBE === "true" || this.outputRBE === true) ? "|rbe| " : "") + (this.name || this.topic || "KNX Device") + ((this.inputRBE === "true" || this.inputRBE === true) ? " |rbe|" : "")
|
|
37
|
+
return ((this.outputRBE === "true" || this.outputRBE === true) ? "|rbe| " : "") + (this.name || this.topic || "KNX Device") + (this.setTopicType === 'str' || this.setTopicType === undefined ? '' : ' [' + this.setTopicType + ']') + ((this.inputRBE === "true" || this.inputRBE === true) ? " |rbe|" : "")
|
|
35
38
|
},
|
|
36
39
|
paletteLabel: "KNX DEVICE",
|
|
37
40
|
// button: {
|
|
@@ -53,16 +56,7 @@
|
|
|
53
56
|
var node = this;
|
|
54
57
|
var oNodeServer = RED.nodes.node($("#node-input-server").val()); // Store the config-node
|
|
55
58
|
$("#tabs").tabs();
|
|
56
|
-
|
|
57
|
-
function fullSearch(sourceText, searchString) {
|
|
58
|
-
// This searches for all words in a string
|
|
59
|
-
var aSearchWords = searchString.toLowerCase().split(" ");
|
|
60
|
-
var i = 0;
|
|
61
|
-
for (let index = 0; index < aSearchWords.length; index++) {
|
|
62
|
-
if (sourceText.toLowerCase().indexOf(aSearchWords[index]) > -1) i += 1;
|
|
63
|
-
}
|
|
64
|
-
return i == aSearchWords.length;
|
|
65
|
-
}
|
|
59
|
+
|
|
66
60
|
|
|
67
61
|
|
|
68
62
|
// 15/09/2020 Supergiovane, set the help sample based on Datapoint
|
|
@@ -152,6 +146,7 @@
|
|
|
152
146
|
|
|
153
147
|
if ($("#node-input-server").val() !== "_ADD_" && $("#node-input-server").val() !== '') {
|
|
154
148
|
$.getJSON("knxUltimateDpts?serverId=" + $("#node-input-server").val() + "&_=" + new Date().getTime(), (data) => {
|
|
149
|
+
$("#node-input-dpt").empty();
|
|
155
150
|
data.forEach(dpt => {
|
|
156
151
|
$("#node-input-dpt").append($("<option></option>")
|
|
157
152
|
.attr("value", dpt.value)
|
|
@@ -229,38 +224,76 @@
|
|
|
229
224
|
}
|
|
230
225
|
})
|
|
231
226
|
|
|
232
|
-
//
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
227
|
+
// Set the group address type
|
|
228
|
+
if (node.setTopicType === undefined) {
|
|
229
|
+
node.setTopicType = 'str';
|
|
230
|
+
$("#node-input-setTopicType").val('str');
|
|
231
|
+
}
|
|
232
|
+
// $("#node-input-topic").typedInput(
|
|
233
|
+
// {
|
|
234
|
+
// default: node.setTopicType || 'str',
|
|
235
|
+
// types: [{ value: 'str', label: "str", icon: 'red/images/typedInput/az.svg', autocomplete: autoCompleteGA }, 'flow', 'global', 'env'],
|
|
236
|
+
// typeField: "#node-input-setTopicType"
|
|
237
|
+
// });
|
|
238
|
+
// var autoCompleteGA = function () {
|
|
239
|
+
// alert(value)
|
|
240
|
+
// return [{ value: "Ciso", label: "maso" }]
|
|
241
|
+
// }
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
$("#node-input-setTopicType").on('change', function () {
|
|
245
|
+
try {
|
|
246
|
+
$("#node-input-topic").autocomplete('destroy');
|
|
247
|
+
$("#node-input-topic").off(); // Rimuovi tutti gli eventi associati
|
|
248
|
+
$("#node-input-topic").val(''); // Pulisce il valore del campo di input, se necessario
|
|
249
|
+
$("#node-input-topic").prop('disabled', false); // Assicura che il campo non sia disabilitato
|
|
250
|
+
$("#node-input-topic").removeClass(); // Rimuove eventuali classi aggiunte dall'autocompletamento
|
|
251
|
+
} catch (error) {
|
|
252
|
+
}
|
|
253
|
+
if ($("#node-input-setTopicType").val() === 'str') {
|
|
254
|
+
$("#node-input-topic").prop('placeholder', 'Select your GA');
|
|
255
|
+
// Autocomplete suggestion with ETS csv File
|
|
256
|
+
$("#node-input-topic").autocomplete({
|
|
257
|
+
minLength: 0,
|
|
258
|
+
source: function (request, response) {
|
|
259
|
+
$.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id + "&" + { _: new Date().getTime() }, (data) => {
|
|
260
|
+
response($.map(data, function (value, key) {
|
|
261
|
+
var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
|
|
262
|
+
if (htmlUtilsfullCSVSearch(sSearch, request.term)) {
|
|
263
|
+
return {
|
|
264
|
+
label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
|
|
265
|
+
value: value.ga // Value
|
|
266
|
+
}
|
|
267
|
+
} else {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
}));
|
|
271
|
+
});
|
|
272
|
+
}, select: function (event, ui) {
|
|
273
|
+
// Sets Datapoint and device name automatically
|
|
274
|
+
var sDevName = ui.item.label.split("#")[1].trim();
|
|
275
|
+
try {
|
|
276
|
+
sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
|
|
277
|
+
} catch (error) {
|
|
246
278
|
}
|
|
247
|
-
|
|
279
|
+
$('#node-input-name').val(sDevName);
|
|
280
|
+
var optVal = $("#node-input-dpt option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
|
|
281
|
+
// Select the option value
|
|
282
|
+
$("#node-input-dpt").val(optVal);
|
|
283
|
+
$("#node-input-dpt").trigger("change");
|
|
284
|
+
}
|
|
285
|
+
}).focus(function () {
|
|
286
|
+
$(this).autocomplete('search', $(this).val() + 'exactmatch');
|
|
248
287
|
});
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
} catch (error) {
|
|
255
|
-
}
|
|
256
|
-
$('#node-input-name').val(sDevName);
|
|
257
|
-
var optVal = $("#node-input-dpt option:contains('" + ui.item.label.split("#")[2].trim() + "')").attr('value');
|
|
258
|
-
// Select the option value
|
|
259
|
-
$("#node-input-dpt").val(optVal);
|
|
260
|
-
$("#node-input-dpt").trigger("change");
|
|
288
|
+
$("#divDatapointSelection").show();
|
|
289
|
+
} else {
|
|
290
|
+
$("#node-input-topic").prop('placeholder', $("#node-input-setTopicType").val());
|
|
291
|
+
if ($("#node-input-topic").val() === '') $("#node-input-topic").val('MyVariable');
|
|
292
|
+
$("#divDatapointSelection").hide();
|
|
261
293
|
}
|
|
262
294
|
});
|
|
263
295
|
|
|
296
|
+
|
|
264
297
|
// Hide or show the GA and DPT fields if Notify on all Group Addresses is checked
|
|
265
298
|
if (oNodeServer !== undefined && oNodeServer !== null) {
|
|
266
299
|
if (oNodeServer.csv !== undefined && oNodeServer.csv !== "") {
|
|
@@ -320,6 +353,8 @@
|
|
|
320
353
|
oneditsave: function () {
|
|
321
354
|
var node = this;
|
|
322
355
|
|
|
356
|
+
//this.propertyType = $("#node-input-property").typedInput('type');
|
|
357
|
+
|
|
323
358
|
// 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
|
|
324
359
|
if ($("#isETSFileLoaded").val() === "no") {
|
|
325
360
|
// Notify the user
|
|
@@ -391,15 +426,22 @@
|
|
|
391
426
|
<div id="divMain">
|
|
392
427
|
|
|
393
428
|
<div id="GAandDPT">
|
|
429
|
+
|
|
394
430
|
<div class="form-row">
|
|
395
431
|
<label for="node-input-topic">
|
|
396
432
|
<img
|
|
397
433
|
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAACXBIWXMAAB7CAAAewgFu0HU+AAAF6WlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgMjEuMSAoTWFjaW50b3NoKSIgeG1wOkNyZWF0ZURhdGU9IjIwMjAtMDMtMjNUMTY6MjE6MDkrMDE6MDAiIHhtcDpNb2RpZnlEYXRlPSIyMDIwLTAzLTIzVDE2OjI4OjI3KzAxOjAwIiB4bXA6TWV0YWRhdGFEYXRlPSIyMDIwLTAzLTIzVDE2OjI4OjI3KzAxOjAwIiBkYzpmb3JtYXQ9ImltYWdlL3BuZyIgcGhvdG9zaG9wOkNvbG9yTW9kZT0iMyIgcGhvdG9zaG9wOklDQ1Byb2ZpbGU9InNSR0IgSUVDNjE5NjYtMi4xIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjc4M2I5OWIxLTkwMjYtNGQ2OC05N2FmLTRkM2E2ZWY4Zjk2OCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4N2E3YTg0NS0xMDljLTRkMTMtOGEzOS04OWVhOTMyMDQ0ZWMiIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo4N2E3YTg0NS0xMDljLTRkMTMtOGEzOS04OWVhOTMyMDQ0ZWMiPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJjcmVhdGVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjg3YTdhODQ1LTEwOWMtNGQxMy04YTM5LTg5ZWE5MzIwNDRlYyIgc3RFdnQ6d2hlbj0iMjAyMC0wMy0yM1QxNjoyMTowOSswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjEgKE1hY2ludG9zaCkiLz4gPHJkZjpsaSBzdEV2dDphY3Rpb249InNhdmVkIiBzdEV2dDppbnN0YW5jZUlEPSJ4bXAuaWlkOjc4M2I5OWIxLTkwMjYtNGQ2OC05N2FmLTRkM2E2ZWY4Zjk2OCIgc3RFdnQ6d2hlbj0iMjAyMC0wMy0yM1QxNjoyODoyNyswMTowMCIgc3RFdnQ6c29mdHdhcmVBZ2VudD0iQWRvYmUgUGhvdG9zaG9wIDIxLjEgKE1hY2ludG9zaCkiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+DGyPFQAAAE9JREFUKJG1UEEOACAIgub/v2yHalnJVoe4uIEKSgccJ9jroVmjA0+ujZtWku3DgZmgBiT4egN9CmmEAAfA/5HUW0OQu7dKmOCzmM3k9YYKZv8ZEZ/YgNsAAAAASUVORK5CYII="></img>
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
434
|
+
Group Addr.</label>
|
|
435
|
+
<select id="node-input-setTopicType" style="width:120px">
|
|
436
|
+
<option value="str">3-Levels</option>
|
|
437
|
+
<option value="flow">Flow</option>
|
|
438
|
+
<option value="global">Gobal</option>
|
|
439
|
+
<option value="env">$Env variable</option>
|
|
440
|
+
</select>
|
|
441
|
+
<input type="text" id="node-input-topic" placeholder="Start typing to search" style="width:180px" />
|
|
401
442
|
</div>
|
|
402
|
-
|
|
443
|
+
|
|
444
|
+
<div class="form-row" id="divDatapointSelection">
|
|
403
445
|
<label for="node-input-dpt">
|
|
404
446
|
<img
|
|
405
447
|
src="data:image/png;base64,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"></img>
|
|
@@ -631,7 +673,8 @@
|
|
|
631
673
|
|Property|Description|
|
|
632
674
|
|--|--|
|
|
633
675
|
| Gateway | Select the KNX gateway to be used |
|
|
634
|
-
|
|
|
676
|
+
| GA Type dropdown list | The group address type. **3-Levels** is the default, where you can type the *3 level group address* or the *group address name* (if you've upload the ETS file), or **Global**, for reading the GA at startup from a global variable, or **Flow** that do the same as the *Global*, but at flow level. Select **$Env variable** to read the group address from an environment variable. |
|
|
677
|
+
| Group Addr. | The KNX Group Address you want to control. If you've imported the ETS group addresses file, you can just start typing in your device name. You can leave it empty if you wish set it with *msg.setConfig* input message. |
|
|
635
678
|
| Datapoint | The datapoint belonging to your node.|
|
|
636
679
|
| Node name | Self explaining. |
|
|
637
680
|
| Topic | The msg output topic. Leave it blank to have it set to your Group Address. |
|
|
@@ -677,19 +720,21 @@
|
|
|
677
720
|
: writeraw (buffer): is used to send a value to the KNX bus, as buffer. Use in conjunction with *bitlenght*.
|
|
678
721
|
: bitlenght (int): specifies the lenght of the *writeraw* buffer. Use in conjunction with *writeraw*.
|
|
679
722
|
: resetRBE (boolean) : resets the internal RBE filters (*use msg.resetRBE = true*).
|
|
680
|
-
:
|
|
723
|
+
: setConfig (json) : programmatically change the KNX-Ultimate Device node Group Address and Datapoint. See details.
|
|
681
724
|
|
|
682
725
|
### Details
|
|
683
726
|
|
|
684
|
-
`msg.
|
|
727
|
+
`msg.setConfig`: It's possible to programmatically change the KNX-Ultimate node configuration, by sending msg.setConfig object to the node.
|
|
685
728
|
The new configuration will be retained until next msg.setConfig or until restart/redeploy.
|
|
686
|
-
All properties
|
|
729
|
+
All properties (*setGroupAddress* and *setDPT*) **are mandatory**..
|
|
687
730
|
Use it like that, in a functon node:
|
|
688
731
|
|
|
689
|
-
|
|
732
|
+
**Set both GA and DPT**
|
|
733
|
+
|
|
734
|
+
```javascript
|
|
690
735
|
// Change the node properties as follows:
|
|
691
736
|
// setGroupAddress: set the new group address.
|
|
692
|
-
// setDPT: set the new Datapoint, as you can see in the dropdown list (the numeric part, for example "1.001", "237.600", etc...)
|
|
737
|
+
// setDPT: set the new Datapoint, as you can see in the dropdown list (the numeric part, for example "1.001", "237.600", etc...). If set to **auto**, the datapoint will be read from the ETS file (if present).
|
|
693
738
|
var config= {
|
|
694
739
|
setGroupAddress: "0/1/2",
|
|
695
740
|
setDPT: "1.001"
|
|
@@ -698,6 +743,20 @@ msg.setConfig = config;
|
|
|
698
743
|
return msg;
|
|
699
744
|
```
|
|
700
745
|
|
|
746
|
+
**Set GA and read the datapoint from the ETS file**
|
|
747
|
+
|
|
748
|
+
```javascript
|
|
749
|
+
// Change the node properties as follows:
|
|
750
|
+
// setGroupAddress: set the new group address.
|
|
751
|
+
// setDPT: set the new Datapoint, as you can see in the dropdown list (the numeric part, for example "1.001", "237.600", etc...). If set to "auto", the datapoint will be read from the ETS file (if present).
|
|
752
|
+
var config= {
|
|
753
|
+
setGroupAddress: "0/1/2",
|
|
754
|
+
setDPT: "auto"
|
|
755
|
+
};
|
|
756
|
+
msg.setConfig = config;
|
|
757
|
+
return msg;
|
|
758
|
+
```
|
|
759
|
+
|
|
701
760
|
### Outputs
|
|
702
761
|
|
|
703
762
|
1. Standard output
|
|
@@ -708,23 +767,31 @@ return msg;
|
|
|
708
767
|
|
|
709
768
|
### Details
|
|
710
769
|
|
|
711
|
-
`msg.payload` is used as the payload of the
|
|
712
|
-
|
|
770
|
+
`msg.payload` is used as the payload of the group address (the group address value).
|
|
771
|
+
This is, instead, an example of the complete msg object.
|
|
713
772
|
|
|
714
773
|
```json
|
|
715
774
|
msg = {
|
|
716
775
|
topic: "0/1/2" // (Contains the node's topic, for example "MyTopic". If the node's topic is not set, contains the Group Address, for example "0/1/2")
|
|
717
776
|
payload: false
|
|
718
|
-
previouspayload: true //
|
|
719
|
-
payloadmeasureunit: "%" //
|
|
720
|
-
payloadsubtypevalue: "Start" //
|
|
721
|
-
devicename: "Dinning table lamp" // (
|
|
722
|
-
|
|
777
|
+
previouspayload: true // Previous node payload value.
|
|
778
|
+
payloadmeasureunit: "%" // Payload's measure unit.
|
|
779
|
+
payloadsubtypevalue: "Start" // Subtype's decoded value, for exampe, On/Off, Ramp/NoRamp, Start/Stop, Alarm/NoAlarm
|
|
780
|
+
devicename: "Dinning table lamp" // If the node is in **universal mode**, it contains the full path (main, middle,name) of the group address name, otherwise, the node name.
|
|
781
|
+
gainfo: { // Contains the details about the group address name and number. This object is only present if the node is set in **universal mode** and with the **ETS file** been imported. If something wrong, it contains the string **unknown**.
|
|
782
|
+
maingroupname:"Light actuators"
|
|
783
|
+
middlegroupname:"First flow lights"
|
|
784
|
+
ganame:"Table Light"
|
|
785
|
+
maingroupnumber:"1"
|
|
786
|
+
middlegroupnumber:"1"
|
|
787
|
+
ganumber:"0"
|
|
788
|
+
}
|
|
789
|
+
knx: { // This is a representation of the KNX BUS telegram, coming from BUS
|
|
723
790
|
event: "GroupValue_Write" // (or "GroupValue_Response", or "GroupValue_Read")
|
|
724
791
|
dpt: "1.001"
|
|
725
|
-
dptdesc: "Humidity" //
|
|
792
|
+
dptdesc: "Humidity" // Payload's measure unit description
|
|
726
793
|
source: "15.15.22"
|
|
727
|
-
destination: "0/1/2" //
|
|
794
|
+
destination: "0/1/2" // Contains the Group Address
|
|
728
795
|
rawValue: buffer[1]raw // (or null, if "GroupValue_Read")
|
|
729
796
|
0: 0x0 // (This is the RAW undecoded value)
|
|
730
797
|
}
|
package/nodes/knxUltimate.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
|
|
1
2
|
/* eslint-disable max-len */
|
|
2
3
|
module.exports = function (RED) {
|
|
3
4
|
const _ = require('lodash');
|
|
4
|
-
const KNXUtils = require('
|
|
5
|
+
const KNXUtils = require('knxultimate');
|
|
5
6
|
const payloadRounder = require('./utils/payloadManipulation');
|
|
6
7
|
|
|
7
8
|
function knxUltimate(config) {
|
|
@@ -13,9 +14,82 @@ module.exports = function (RED) {
|
|
|
13
14
|
node.status({ fill: 'red', shape: 'dot', text: '[THE GATEWAY NODE HAS BEEN DISABLED]' });
|
|
14
15
|
return;
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
node.
|
|
17
|
+
|
|
18
|
+
// Used to call the status update from the config node.
|
|
19
|
+
node.setNodeStatus = ({
|
|
20
|
+
fill, shape, text, payload, GA, dpt, devicename,
|
|
21
|
+
}) => {
|
|
22
|
+
try {
|
|
23
|
+
if (node.server == null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return; }
|
|
24
|
+
if (node.icountMessageInWindow == -999) return; // Locked out, doesn't change status.
|
|
25
|
+
const dDate = new Date();
|
|
26
|
+
// 30/08/2019 Display only the things selected in the config
|
|
27
|
+
GA = (typeof GA === 'undefined' || GA == '') ? '' : `(${GA}) `;
|
|
28
|
+
devicename = devicename || '';
|
|
29
|
+
dpt = (typeof dpt === 'undefined' || dpt == '') ? '' : ` DPT${dpt}`;
|
|
30
|
+
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload;
|
|
31
|
+
node.status({ fill, shape, text: `${GA + payload + (node.listenallga === true ? ` ${devicename}` : '')} (${dDate.getDate()}, ${dDate.toLocaleTimeString()} ${text}` });
|
|
32
|
+
// 16/02/2020 signal errors to the server
|
|
33
|
+
if (fill.toUpperCase() === 'RED') {
|
|
34
|
+
if (node.server) {
|
|
35
|
+
const oError = {
|
|
36
|
+
nodeid: node.id, topic: node.outputtopic, devicename, GA, text,
|
|
37
|
+
};
|
|
38
|
+
node.server.reportToWatchdogCalledByKNXUltimateNode(oError);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Validate the Address to advise the user. The address can be undefined, because the
|
|
42
|
+
// group address can be set via setConfig
|
|
43
|
+
if (node.listenallga === false) {
|
|
44
|
+
try {
|
|
45
|
+
KNXUtils.validateKNXAddress(node.topic, true);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
node.setNodeStatus({
|
|
48
|
+
fill: 'grey', shape: 'ring', text: "DISABLED: " + error.message, payload: '', GA: node.topic, dpt: '', devicename: '',
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
} catch (error) {
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
// Get the Group Address from various sources
|
|
61
|
+
if (config.setTopicType === undefined || config.setTopicType === 'str') {
|
|
62
|
+
node.topic = config.topic;
|
|
63
|
+
node.dpt = config.dpt || '1.001';
|
|
64
|
+
} else if (config.setTopicType === 'flow') {
|
|
65
|
+
try {
|
|
66
|
+
node.topic = node.context().flow.get(config.topic);
|
|
67
|
+
node.dpt = 'auto';
|
|
68
|
+
payloadRounder.KNXULtimateChangeConfigByInputMSG({ setConfig: { setGroupAddress: node.topic, setDPT: node.dpt } }, node, config);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
node.topic = undefined;
|
|
71
|
+
}
|
|
72
|
+
} else if (config.setTopicType === 'global') {
|
|
73
|
+
try {
|
|
74
|
+
node.topic = node.context().global.get(config.topic);
|
|
75
|
+
node.dpt = 'auto';
|
|
76
|
+
payloadRounder.KNXULtimateChangeConfigByInputMSG({ setConfig: { setGroupAddress: node.topic, setDPT: node.dpt } }, node, config);
|
|
77
|
+
} catch (error) {
|
|
78
|
+
node.topic = undefined;
|
|
79
|
+
}
|
|
80
|
+
} else if (config.setTopicType === 'env') {
|
|
81
|
+
try {
|
|
82
|
+
node.topic = RED.util.getSetting(node, config.topic); // takes care of the subflow's env vairables
|
|
83
|
+
node.dpt = 'auto';
|
|
84
|
+
payloadRounder.KNXULtimateChangeConfigByInputMSG({ setConfig: { setGroupAddress: node.topic, setDPT: node.dpt } }, node, config);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
node.topic = undefined;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
node.outputtopic = (config.outputtopic === undefined || config.outputtopic === '') ? node.topic : config.outputtopic; // 07/02/2020 Importante, per retrocompatibilità
|
|
92
|
+
node.name = config.name;
|
|
19
93
|
node.notifyreadrequest = config.notifyreadrequest || false;
|
|
20
94
|
node.notifyreadrequestalsorespondtobus = config.notifyreadrequestalsorespondtobus || 'false'; // Auto respond if notifireadrequest is true
|
|
21
95
|
node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = config.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized || '';
|
|
@@ -47,48 +121,11 @@ module.exports = function (RED) {
|
|
|
47
121
|
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
|
|
48
122
|
|
|
49
123
|
|
|
50
|
-
|
|
51
|
-
// Used to call the status update from the config node.
|
|
52
|
-
node.setNodeStatus = ({
|
|
53
|
-
fill, shape, text, payload, GA, dpt, devicename,
|
|
54
|
-
}) => {
|
|
55
|
-
try {
|
|
56
|
-
if (node.server == null) { node.status({ fill: 'red', shape: 'dot', text: '[NO GATEWAY SELECTED]' }); return; }
|
|
57
|
-
if (node.icountMessageInWindow == -999) return; // Locked out, doesn't change status.
|
|
58
|
-
const dDate = new Date();
|
|
59
|
-
// 30/08/2019 Display only the things selected in the config
|
|
60
|
-
GA = (typeof GA === 'undefined' || GA == '') ? '' : `(${GA}) `;
|
|
61
|
-
devicename = devicename || '';
|
|
62
|
-
dpt = (typeof dpt === 'undefined' || dpt == '') ? '' : ` DPT${dpt}`;
|
|
63
|
-
payload = typeof payload === 'object' ? JSON.stringify(payload) : payload;
|
|
64
|
-
node.status({ fill, shape, text: `${GA + payload + (node.listenallga === true ? ` ${devicename}` : '')} (${dDate.getDate()}, ${dDate.toLocaleTimeString()} ${text}` });
|
|
65
|
-
// 16/02/2020 signal errors to the server
|
|
66
|
-
if (fill.toUpperCase() === 'RED') {
|
|
67
|
-
if (node.server) {
|
|
68
|
-
const oError = {
|
|
69
|
-
nodeid: node.id, topic: node.outputtopic, devicename, GA, text,
|
|
70
|
-
};
|
|
71
|
-
node.server.reportToWatchdogCalledByKNXUltimateNode(oError);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
} catch (error) {
|
|
75
|
-
}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
// Check if the node has a valid topic and dpt
|
|
124
|
+
// Check if the node has a valid dpt
|
|
79
125
|
if (node.listenallga === false) {
|
|
80
|
-
if (node.
|
|
81
|
-
node.setNodeStatus({
|
|
82
|
-
fill: 'red', shape: 'dot', text: 'Empty Group Addr. or datapoint.', payload: '', GA: '', dpt: '', devicename: '',
|
|
83
|
-
});
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
// Validate the Address
|
|
87
|
-
try {
|
|
88
|
-
KNXUtils.validateKNXAddress(node.topic, true);
|
|
89
|
-
} catch (error) {
|
|
126
|
+
if (node.dpt === undefined || node.dpt === '') {
|
|
90
127
|
node.setNodeStatus({
|
|
91
|
-
fill: 'red', shape: 'dot', text:
|
|
128
|
+
fill: 'red', shape: 'dot', text: 'The Datapoint cannot be empty.', payload: '', GA: '', dpt: '', devicename: '',
|
|
92
129
|
});
|
|
93
130
|
return;
|
|
94
131
|
}
|
|
@@ -113,6 +150,7 @@ module.exports = function (RED) {
|
|
|
113
150
|
node.send(msg);
|
|
114
151
|
};
|
|
115
152
|
|
|
153
|
+
|
|
116
154
|
node.on('input', (msg) => {
|
|
117
155
|
if (typeof msg === 'undefined') return;
|
|
118
156
|
if (!node.server) return; // 29/08/2019 Server not instantiate
|
|
@@ -120,22 +158,24 @@ module.exports = function (RED) {
|
|
|
120
158
|
// 11/01/2021 Accept properties change from msg
|
|
121
159
|
// *********************************
|
|
122
160
|
if (msg.hasOwnProperty('setConfig')) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
161
|
+
payloadRounder.KNXULtimateChangeConfigByInputMSG(msg, node, config);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
// *********************************
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
// 16/06/2024 Check wether the node has a group address set.
|
|
168
|
+
// Validate the Address
|
|
169
|
+
if (node.listenallga === false) {
|
|
170
|
+
try {
|
|
171
|
+
KNXUtils.validateKNXAddress(node.topic, true);
|
|
172
|
+
} catch (error) {
|
|
133
173
|
node.setNodeStatus({
|
|
134
|
-
fill: '
|
|
174
|
+
fill: 'red', shape: 'dot', text: error.message, payload: '', GA: node.topic, dpt: '', devicename: '',
|
|
135
175
|
});
|
|
176
|
+
return;
|
|
136
177
|
}
|
|
137
178
|
}
|
|
138
|
-
// *********************************
|
|
139
179
|
|
|
140
180
|
// 19/06/2022 Reset the RBE filter https://github.com/Supergiovane/node-red-contrib-knx-ultimate/issues/191
|
|
141
181
|
// *********************************
|
|
@@ -241,7 +281,7 @@ module.exports = function (RED) {
|
|
|
241
281
|
}
|
|
242
282
|
}
|
|
243
283
|
} else {
|
|
244
|
-
if (node.listenallga
|
|
284
|
+
if (node.listenallga === false) {
|
|
245
285
|
// 23/12/2020 Applying RBE filter
|
|
246
286
|
if (node.outputRBE === "true") {
|
|
247
287
|
// 19/01/2023 CHECKING THE INPUT PAYLOAD (ROUND, ETC) BASED ON THE NODE CONFIG
|
|
@@ -287,7 +327,7 @@ module.exports = function (RED) {
|
|
|
287
327
|
if (msg.event === 'Update_NoWrite') outputtype = 'update'; // 05/01/2021 Doesn't send anything to the bus. Only updates the node currentPayload
|
|
288
328
|
}
|
|
289
329
|
|
|
290
|
-
if (node.listenallga
|
|
330
|
+
if (node.listenallga === true) {
|
|
291
331
|
// The node is set to Universal mode (listen to all Group Addresses). Some fields are needed
|
|
292
332
|
if (msg.hasOwnProperty('destination')) {
|
|
293
333
|
grpaddr = msg.destination;
|
|
@@ -297,7 +337,7 @@ module.exports = function (RED) {
|
|
|
297
337
|
});
|
|
298
338
|
return;
|
|
299
339
|
}
|
|
300
|
-
if (msg.hasOwnProperty('dpt')) {
|
|
340
|
+
if (msg.hasOwnProperty('dpt') && msg.dpt !== undefined && msg.dpt !== '') {
|
|
301
341
|
dpt = msg.dpt;
|
|
302
342
|
} else {
|
|
303
343
|
// No datapoint set. If the CSV is loaded, try to get it from there.
|
|
@@ -325,7 +365,7 @@ module.exports = function (RED) {
|
|
|
325
365
|
}
|
|
326
366
|
} else {
|
|
327
367
|
grpaddr = msg.hasOwnProperty('destination') ? msg.destination : node.topic;
|
|
328
|
-
dpt = msg.hasOwnProperty('dpt') ? msg.dpt : node.dpt;
|
|
368
|
+
dpt = (msg.hasOwnProperty('dpt') && msg.dpt !== undefined && msg.dpt !== '') ? msg.dpt : node.dpt;
|
|
329
369
|
}
|
|
330
370
|
|
|
331
371
|
// Protection over circular references (for example, if you link two Ultimate Nodes toghether with the same group address), to prevent infinite loops
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/htmlUtils.js"></script>
|
|
2
|
+
|
|
1
3
|
<script type="text/javascript">
|
|
2
4
|
RED.nodes.registerType('knxUltimateAlerter', {
|
|
3
5
|
category: "KNX Ultimate",
|
|
@@ -45,16 +47,7 @@
|
|
|
45
47
|
} catch (error) { }
|
|
46
48
|
});
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
function fullSearch(sourceText, searchString) {
|
|
50
|
-
// This searches for all words in a string
|
|
51
|
-
var aSearchWords = searchString.toLowerCase().split(" ");
|
|
52
|
-
var i = 0;
|
|
53
|
-
for (let index = 0; index < aSearchWords.length; index++) {
|
|
54
|
-
if (sourceText.toLowerCase().indexOf(aSearchWords[index]) > -1) i += 1;
|
|
55
|
-
}
|
|
56
|
-
return i == aSearchWords.length;
|
|
57
|
-
}
|
|
50
|
+
|
|
58
51
|
|
|
59
52
|
|
|
60
53
|
// Scene configuration
|
|
@@ -90,12 +83,12 @@
|
|
|
90
83
|
|
|
91
84
|
// Autocomplete suggestion with ETS csv File
|
|
92
85
|
oTopicField.autocomplete({
|
|
93
|
-
minLength:
|
|
86
|
+
minLength: 0,
|
|
94
87
|
source: function (request, response) {
|
|
95
88
|
$.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
|
|
96
89
|
response($.map(data, function (value, key) {
|
|
97
90
|
var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
|
|
98
|
-
if (
|
|
91
|
+
if (htmlUtilsfullCSVSearch(sSearch, request.term + " 1.")) {
|
|
99
92
|
return {
|
|
100
93
|
label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
|
|
101
94
|
value: value.ga // Value
|
|
@@ -116,6 +109,8 @@
|
|
|
116
109
|
}
|
|
117
110
|
|
|
118
111
|
}
|
|
112
|
+
}).focus(function () {
|
|
113
|
+
$(this).autocomplete('search', $(this).val() + 'exactmatch');
|
|
119
114
|
});
|
|
120
115
|
|
|
121
116
|
oTopicField.val(rule.topic);
|
|
@@ -4,8 +4,8 @@ module.exports = function (RED) {
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const mkdirp = require('mkdirp');
|
|
7
|
-
// const Address = require('
|
|
8
|
-
// const KnxConstants = require('
|
|
7
|
+
// const Address = require('knxultimate')
|
|
8
|
+
// const KnxConstants = require('knxultimate/protocol/KNXConstants')
|
|
9
9
|
|
|
10
10
|
RED.nodes.createNode(this, config);
|
|
11
11
|
const node = this;
|
|
@@ -209,6 +209,7 @@ module.exports = function (RED) {
|
|
|
209
209
|
node.setLocalStatus({ fill: 'grey', shape: 'dot', text: 'ERROR: You must provide payload (true/false)', payload: '', GA: '', dpt: '', devicename: '' });
|
|
210
210
|
return;
|
|
211
211
|
}
|
|
212
|
+
|
|
212
213
|
msg.knx = { dpt: '1.001' };
|
|
213
214
|
node.handleSend(msg);
|
|
214
215
|
});
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
<script type="text/javascript" src="resources/node-red-contrib-knx-ultimate/htmlUtils.js"></script>
|
|
2
|
+
|
|
1
3
|
<script type="text/javascript">
|
|
2
4
|
RED.nodes.registerType('knxUltimateGarageDoorBarrierOpener', {
|
|
3
5
|
category: "KNX Ultimate",
|
|
@@ -48,7 +50,7 @@
|
|
|
48
50
|
|
|
49
51
|
function getGroupAddressSimple(_sourceWidgetAutocomplete, _additionalSearchTerm) {
|
|
50
52
|
$(_sourceWidgetAutocomplete).autocomplete({
|
|
51
|
-
minLength:
|
|
53
|
+
minLength: 0,
|
|
52
54
|
source: function (request, response) {
|
|
53
55
|
//$.getJSON("csv", request, function( data, status, xhr ) {
|
|
54
56
|
$.getJSON("knxUltimatecsv?nodeID=" + $("#node-input-server").val() + "&" + { _: new Date().getTime() }, (data) => {
|
|
@@ -57,7 +59,7 @@
|
|
|
57
59
|
var sSearch = value.ga + " (" + value.devicename + ") DPT" + value.dpt;
|
|
58
60
|
for (let index = 0; index < _additionalSearchTerm.length; index++) {
|
|
59
61
|
const sDPT = _additionalSearchTerm[index];
|
|
60
|
-
if (
|
|
62
|
+
if (htmlUtilsfullCSVSearch(sSearch, request.term + " " + sDPT)) {
|
|
61
63
|
return {
|
|
62
64
|
label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
|
|
63
65
|
value: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
|
|
@@ -73,19 +75,12 @@
|
|
|
73
75
|
const sDevName = ui.item.value.trim();
|
|
74
76
|
$(_sourceWidgetAutocomplete).val(sDevName);
|
|
75
77
|
},
|
|
78
|
+
}).focus(function () {
|
|
79
|
+
$(this).autocomplete('search', $(this).val() + 'exactmatch');
|
|
76
80
|
});
|
|
77
81
|
}
|
|
78
82
|
|
|
79
|
-
|
|
80
|
-
function fullSearch(sourceText, searchString) {
|
|
81
|
-
// This searches for all words in a string
|
|
82
|
-
var aSearchWords = searchString.toLowerCase().split(" ");
|
|
83
|
-
var i = 0;
|
|
84
|
-
for (let index = 0; index < aSearchWords.length; index++) {
|
|
85
|
-
if (sourceText.toLowerCase().indexOf(aSearchWords[index]) > -1) i += 1;
|
|
86
|
-
}
|
|
87
|
-
return i == aSearchWords.length;
|
|
88
|
-
}
|
|
83
|
+
|
|
89
84
|
|
|
90
85
|
if (oNodeServer === undefined) {
|
|
91
86
|
// Hide the UI
|