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.
Files changed (153) hide show
  1. package/.eslintrc.json +3 -2
  2. package/CHANGELOG.md +13 -0
  3. package/README.md +2 -1
  4. package/{KNXEngine → _JS_KNXEngine}/README.md +7 -7
  5. package/{KNXEngine → _JS_KNXEngine}/index.js +1 -1
  6. package/{KNXEngine → _JS_KNXEngine}/sample.js +5 -5
  7. package/{KNXEngine → _JS_KNXEngine}/sampleSecure.js +1 -1
  8. package/{KNXEngine → _JS_KNXEngine}/src/KNXClient.js +3 -3
  9. package/_JS_KNXEngine/src/dptlib/dpt60002.js +101 -0
  10. package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectResponse.js +2 -0
  11. package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConstants.js +1 -0
  12. package/nodes/commonFunctions.js +3 -3
  13. package/nodes/hue-config.html +2 -0
  14. package/nodes/hue-config.js +8 -0
  15. package/nodes/knxUltimate-config.html +2 -0
  16. package/nodes/knxUltimate-config.js +226 -223
  17. package/nodes/knxUltimate.html +124 -57
  18. package/nodes/knxUltimate.js +100 -60
  19. package/nodes/knxUltimateAlerter.html +7 -12
  20. package/nodes/knxUltimateAlerter.js +3 -2
  21. package/nodes/knxUltimateGarageDoorBarrierOpener.html +7 -12
  22. package/nodes/knxUltimateGarageDoorBarrierOpener.js +2 -2
  23. package/nodes/knxUltimateGlobalContext.html +2 -0
  24. package/nodes/knxUltimateHueBattery.html +11 -14
  25. package/nodes/knxUltimateHueButton.html +27 -22
  26. package/nodes/knxUltimateHueButton.js +1 -1
  27. package/nodes/knxUltimateHueContactSensor.html +12 -8
  28. package/nodes/knxUltimateHueLight.html +17 -24
  29. package/nodes/knxUltimateHueLight.js +1 -2
  30. package/nodes/knxUltimateHueLightSensor.html +11 -14
  31. package/nodes/knxUltimateHueMotion.html +11 -14
  32. package/nodes/knxUltimateHueScene.html +24 -19
  33. package/nodes/knxUltimateHueScene.js +2 -1
  34. package/nodes/knxUltimateHueTapDial.html +11 -14
  35. package/nodes/knxUltimateHueTemperatureSensor.html +11 -14
  36. package/nodes/knxUltimateHueZigbeeConnectivity.html +11 -14
  37. package/nodes/knxUltimateHuedevice_software_update.html +261 -0
  38. package/nodes/knxUltimateHuedevice_software_update.js +134 -0
  39. package/nodes/knxUltimateLoadControl.html +4 -11
  40. package/nodes/knxUltimateLoadControl.js +1 -1
  41. package/nodes/knxUltimateLogger.html +3 -1
  42. package/nodes/knxUltimateSceneController.html +14 -15
  43. package/nodes/knxUltimateViewer.html +2 -0
  44. package/nodes/knxUltimateViewer.js +1 -1
  45. package/nodes/knxUltimateWatchDog.html +3 -1
  46. package/nodes/utils/payloadManipulation.js +49 -1
  47. package/nodes/utils/utils.js +4 -0
  48. package/package.json +6 -4
  49. package/resources/htmlUtils.js +27 -0
  50. /package/{KNXEngine → _JS_KNXEngine}/CHANGELOG.md +0 -0
  51. /package/{KNXEngine → _JS_KNXEngine}/LICENSE +0 -0
  52. /package/{KNXEngine → _JS_KNXEngine}/img/dpt 2.png +0 -0
  53. /package/{KNXEngine → _JS_KNXEngine}/img/dpt.png +0 -0
  54. /package/{KNXEngine → _JS_KNXEngine}/img/logo 2.png +0 -0
  55. /package/{KNXEngine → _JS_KNXEngine}/img/logo-big 2.png +0 -0
  56. /package/{KNXEngine → _JS_KNXEngine}/img/logo-big.png +0 -0
  57. /package/{KNXEngine → _JS_KNXEngine}/img/logo.png +0 -0
  58. /package/{KNXEngine → _JS_KNXEngine}/img/nodered 2.png +0 -0
  59. /package/{KNXEngine → _JS_KNXEngine}/img/nodered.png +0 -0
  60. /package/{KNXEngine → _JS_KNXEngine}/package.json +0 -0
  61. /package/{KNXEngine → _JS_KNXEngine}/simpleSample.js +0 -0
  62. /package/{KNXEngine → _JS_KNXEngine}/src/Curve25519.js +0 -0
  63. /package/{KNXEngine → _JS_KNXEngine}/src/KNXSocketOptions.js +0 -0
  64. /package/{KNXEngine → _JS_KNXEngine}/src/KNXsecureKeyring.js +0 -0
  65. /package/{KNXEngine → _JS_KNXEngine}/src/KnxLog.js +0 -0
  66. /package/{KNXEngine → _JS_KNXEngine}/src/cur.js +0 -0
  67. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt1.js +0 -0
  68. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt10.js +0 -0
  69. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt11.js +0 -0
  70. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt12.js +0 -0
  71. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt13.js +0 -0
  72. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt14.js +0 -0
  73. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt15.js +0 -0
  74. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt16.js +0 -0
  75. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt17.js +0 -0
  76. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt18.js +0 -0
  77. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt19.js +0 -0
  78. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt2.js +0 -0
  79. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt20.js +0 -0
  80. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt21.js +0 -0
  81. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt213.js +0 -0
  82. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt22.js +0 -0
  83. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt222.js +0 -0
  84. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt232.js +0 -0
  85. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt235.js +0 -0
  86. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt237.js +0 -0
  87. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt238.js +0 -0
  88. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt242.js +0 -0
  89. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt249.js +0 -0
  90. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt251.js +0 -0
  91. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt275.js +0 -0
  92. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt28.js +0 -0
  93. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt29.js +0 -0
  94. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt3.js +0 -0
  95. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt4.js +0 -0
  96. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt5.js +0 -0
  97. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt6.js +0 -0
  98. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt60001.js +0 -0
  99. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt7.js +0 -0
  100. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt8.js +0 -0
  101. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt9.js +0 -0
  102. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/dpt999.js +0 -0
  103. /package/{KNXEngine → _JS_KNXEngine}/src/dptlib/index.js +0 -0
  104. /package/{KNXEngine → _JS_KNXEngine}/src/errors/BufferLengthError.js +0 -0
  105. /package/{KNXEngine → _JS_KNXEngine}/src/errors/DateFormatError.js +0 -0
  106. /package/{KNXEngine → _JS_KNXEngine}/src/errors/DuplicateRequestError.js +0 -0
  107. /package/{KNXEngine → _JS_KNXEngine}/src/errors/InvalidValueError.js +0 -0
  108. /package/{KNXEngine → _JS_KNXEngine}/src/errors/NotImplementedError.js +0 -0
  109. /package/{KNXEngine → _JS_KNXEngine}/src/errors/RequestTimeoutError.js +0 -0
  110. /package/{KNXEngine → _JS_KNXEngine}/src/errors/index.js +0 -0
  111. /package/{KNXEngine → _JS_KNXEngine}/src/index.js +0 -0
  112. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/CRD.js +0 -0
  113. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/CRI.js +0 -0
  114. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/CRIFactory.js +0 -0
  115. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/DIB.js +0 -0
  116. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/DeviceInfo.js +0 -0
  117. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/HPAI.js +0 -0
  118. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/IPConfig.js +0 -0
  119. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/IPCurrentConfig.js +0 -0
  120. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXAddress.js +0 -0
  121. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXAddresses.js +0 -0
  122. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectRequest.js +0 -0
  123. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectionStateRequest.js +0 -0
  124. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXConnectionStateResponse.js +0 -0
  125. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDataBuffer.js +0 -0
  126. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDescriptionRequest.js +0 -0
  127. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDescriptionResponse.js +0 -0
  128. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDisconnectRequest.js +0 -0
  129. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXDisconnectResponse.js +0 -0
  130. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXHeader.js +0 -0
  131. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXPacket.js +0 -0
  132. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXProtocol.js +0 -0
  133. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXRoutingIndication.js +0 -0
  134. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXSearchRequest.js +0 -0
  135. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXSearchResponse.js +0 -0
  136. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXSecureSessionRequest.js +0 -0
  137. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXTunnelingAck.js +0 -0
  138. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXTunnelingRequest.js +0 -0
  139. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/KNXUtils.js +0 -0
  140. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/ServiceFamilies.js +0 -0
  141. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/TunnelCRI.js +0 -0
  142. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/AdditionalInfo.js +0 -0
  143. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/CEMIConstants.js +0 -0
  144. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/CEMIFactory.js +0 -0
  145. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/CEMIMessage.js +0 -0
  146. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/ControlField.js +0 -0
  147. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/LDataCon.js +0 -0
  148. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/LDataInd.js +0 -0
  149. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/LDataReq.js +0 -0
  150. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/NPDU.js +0 -0
  151. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/cEMI/TLVInfo.js +0 -0
  152. /package/{KNXEngine → _JS_KNXEngine}/src/protocol/index.js +0 -0
  153. /package/{KNXEngine → _JS_KNXEngine}/src/util/ipAddressHelper.js +0 -0
@@ -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
- // 31/03/2020 Search Helper
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
- // Autocomplete suggestion with ETS csv File
233
- $("#node-input-topic").autocomplete({
234
- minLength: 1,
235
- source: function (request, response) {
236
- $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id + "&" + { _: new Date().getTime() }, (data) => {
237
- response($.map(data, function (value, key) {
238
- var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
239
- if (fullSearch(sSearch, request.term)) {
240
- return {
241
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
242
- value: value.ga // Value
243
- }
244
- } else {
245
- return null;
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
- }, select: function (event, ui) {
250
- // Sets Datapoint and device name automatically
251
- var sDevName = ui.item.label.split("#")[1].trim();
252
- try {
253
- sDevName = sDevName.substr(sDevName.indexOf(")") + 1).trim();
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
- <span data-i18n="knxUltimate.properties.node-input-topic"></span>
399
- </label>
400
- <input type="text" id="node-input-topic" placeholder="Sample: Dinning light" />
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
- <div class="form-row">
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
- | 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. |
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
- : config (json) : programmatically change the KNX-Ultimate Device node configuration. See details.
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.config`: It's possible to programmatically change the KNX-Ultimate node configuration, by sending msg.setConfig object to the node.
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 are optional, that means, you can change only the properties you need.
729
+ All properties (*setGroupAddress* and *setDPT*) **are mandatory**..
687
730
  Use it like that, in a functon node:
688
731
 
689
- ```json
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 published message.
712
- If it contains an Object it will be converted to a JSON string before being sent.
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 // (Previous node payload value.)
719
- payloadmeasureunit: "%" // (payload's measure unit)
720
- payloadsubtypevalue: "Start" // (Subtype's decoded value, for exampe, On/Off, Ramp/NoRamp, Start/Stop, Alarm/NoAlarm)
721
- devicename: "Dinning table lamp" // (Contains the node's name)
722
- knx: {
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" // (payload's measure unit description)
792
+ dptdesc: "Humidity" // Payload's measure unit description
726
793
  source: "15.15.22"
727
- destination: "0/1/2" // (Contains the Group Address of the incoming telegram)
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
  }
@@ -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('../KNXEngine/src/protocol/KNXUtils');
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
- node.topic = config.topic;
17
- node.outputtopic = (config.outputtopic === undefined || config.outputtopic === '') ? config.topic : config.outputtopic; // 07/02/2020 Importante, per retrocompatibilità
18
- node.dpt = config.dpt || '1.001';
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.topic === undefined || node.dpt === undefined) {
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: error.message, payload: '', GA: node.topic, dpt: '', devicename: '',
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
- if (msg.setConfig.hasOwnProperty('setDPT')) {
124
- node.dpt = msg.setConfig.setDPT;
125
- if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.info(`knxUltimate: new datapoint set by msg: ${node.dpt}`);
126
- node.setNodeStatus({
127
- fill: 'grey', shape: 'ring', text: `Datapoint changed to ${node.dpt}`, payload: '', GA: '', dpt: '', devicename: '',
128
- });
129
- }
130
- if (msg.setConfig.hasOwnProperty('setGroupAddress')) {
131
- node.topic = msg.setConfig.setGroupAddress;
132
- if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.info(`knxUltimate: new GroupAddress set by msg: ${node.topic}`);
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: 'grey', shape: 'ring', text: `GroupAddress changed to ${node.topic}`, payload: '', GA: '', dpt: '', devicename: '',
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 == false) {
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 == true) {
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
- // 31/03/2020 Search Helper
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: 1,
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 (fullSearch(sSearch, request.term)) {
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('./../KNXEngine/src/protocol/KNXAddress')
8
- // const KnxConstants = require('./../KNXEngine/src/protocol/KNXConstants')
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: 1,
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 (fullSearch(sSearch, request.term + " " + sDPT)) {
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
- // 31/03/2020 Search Helper
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