node-red-contrib-knx-ultimate 2.1.53 → 2.1.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,8 +7,12 @@
7
7
  # CHANGELOG
8
8
 
9
9
  <p>
10
- <b>Version 2.1.53</b> - October 2023<br/>
11
- - Fixed descriptive error in case the HUE bridge's IP is wrong.<br/>
10
+ <b>Version 2.1.55</b> - October 2023<br/>
11
+ - HUE Scene: removed non existant scene 0.<br/>
12
+ </p>
13
+ <p>
14
+ <b>Version 2.1.54</b> - October 2023<br/>
15
+ - HUE Scene: NEW: you can now use also the Datapoint 18.001, to recall a scene via a KNX scene pushbutton.<br/>
12
16
  </p>
13
17
  <p>
14
18
  <b>Version 2.1.52</b> - October 2023<br/>
@@ -195,6 +195,8 @@
195
195
 
196
196
  <br/>
197
197
 
198
+ <p>
199
+ <b>KNX</b>
198
200
  </p>
199
201
 
200
202
  <div class="form-row">
@@ -210,8 +212,7 @@
210
212
  <input type="text" id="node-input-namebatterysensor" style="width:200px;margin-left: 5px; text-align: left;">
211
213
  </div>
212
214
 
213
- </div>
214
-
215
+
215
216
 
216
217
  <br/>
217
218
  <br/>
@@ -342,6 +342,8 @@
342
342
 
343
343
  <br/>
344
344
 
345
+ <p>
346
+ <b>KNX</b>
345
347
  </p>
346
348
 
347
349
  <div class="form-row">
@@ -395,7 +397,6 @@
395
397
  </label>
396
398
  </div>
397
399
 
398
- </div>
399
400
 
400
401
 
401
402
  <br/>
@@ -194,6 +194,8 @@
194
194
 
195
195
  <br/>
196
196
 
197
+ <p>
198
+ <b>KNX</b>
197
199
  </p>
198
200
 
199
201
  <div class="form-row">
@@ -209,7 +211,7 @@
209
211
  <input type="text" id="node-input-namelightsensor" style="width:200px;margin-left: 5px; text-align: left;">
210
212
  </div>
211
213
 
212
- </div>
214
+
213
215
 
214
216
 
215
217
  <br/>
@@ -194,6 +194,8 @@
194
194
 
195
195
  <br/>
196
196
 
197
+ <p>
198
+ <b>KNX</b>
197
199
  </p>
198
200
 
199
201
  <div class="form-row">
@@ -209,10 +211,7 @@
209
211
  <input type="text" id="node-input-namemotion" style="width:200px;margin-left: 5px; text-align: left;">
210
212
  </div>
211
213
 
212
- </div>
213
-
214
-
215
- <br/>
214
+ s<br/>
216
215
  <br/>
217
216
  <br/>
218
217
 
@@ -11,6 +11,7 @@
11
11
  namescene: { value: "" },
12
12
  GAscene: { value: "" },
13
13
  dptscene: { value: "" },
14
+ valscene: { value: 0 }, // the scene number or true/false
14
15
 
15
16
  hueDevice: { value: "" },
16
17
  hueSceneRecallType: { value: "active" }
@@ -41,6 +42,14 @@
41
42
  var oNodeServer = RED.nodes.node($("#node-input-server").val()); // Store the config-node
42
43
  var oNodeServerHue = RED.nodes.node($("#node-input-serverHue").val()); // Store the config-node
43
44
 
45
+ for (let index = 1; index < 64; index++) {
46
+ $("#node-input-valscene").append($("<option></option>")
47
+ .attr("value", index)
48
+ .text("Scene n. " + index)
49
+ )
50
+ }
51
+ $("#node-input-valscene").val(node.valscene)
52
+
44
53
  // 19/02/2020 Used to get the server sooner als deploy.
45
54
  $("#node-input-server").change(function () {
46
55
  try {
@@ -69,13 +78,14 @@
69
78
  // ########################
70
79
  $.getJSON('knxUltimateDpts', (data) => {
71
80
  data.forEach(dpt => {
72
- if (dpt.value.startsWith("1.")) {
81
+ if (dpt.value.startsWith("1.") || dpt.value.startsWith("18.")) {
73
82
  $("#node-input-dptscene").append($("<option></option>")
74
83
  .attr("value", dpt.value)
75
84
  .text(dpt.text))
76
85
  }
77
86
  });
78
87
  $("#node-input-dptscene").val(this.dptscene)
88
+ ShowHideValScene();
79
89
  })
80
90
 
81
91
  // Autocomplete suggestion with ETS csv File
@@ -86,11 +96,13 @@
86
96
  $.getJSON("knxUltimatecsv?nodeID=" + oNodeServer.id, (data) => {
87
97
  response($.map(data, function (value, key) {
88
98
  var sSearch = (value.ga + " (" + value.devicename + ") DPT" + value.dpt);
89
- if (fullSearch(sSearch, request.term + " 1.")) {
90
- return {
91
- label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
92
- value: value.ga // Value
93
- }
99
+ if (fullSearch(sSearch, request.term)) {
100
+ if (value.dpt.startsWith("1.") || value.dpt.startsWith("18.")) {
101
+ return {
102
+ label: value.ga + " # " + value.devicename + " # " + value.dpt, // Label for Display
103
+ value: value.ga // Value
104
+ }
105
+ } else { return null; }
94
106
  } else {
95
107
  return null;
96
108
  }
@@ -111,8 +123,22 @@
111
123
  });
112
124
  // ########################
113
125
 
114
-
115
-
126
+ function ShowHideValScene() {
127
+ if ($("#node-input-dptscene").val() !== null) {
128
+ // Adapt the scene value/true
129
+ if ($("#node-input-dptscene").val().startsWith("1.")) {
130
+ $("#divValScene").hide();
131
+ //$("#node-input-valscene").attr("disabled", "disabled");
132
+ } else {
133
+ $("#divValScene").show()
134
+ //$("#node-input-valscene").removeAttr("disabled");
135
+ }
136
+ }
137
+ }
138
+ $("#node-input-dptscene").on("change", function () {
139
+ ShowHideValScene()
140
+ });
141
+ ShowHideValScene();
116
142
 
117
143
  // Autocomplete suggestion with HUE
118
144
  $("#node-input-name").autocomplete({
@@ -137,10 +163,7 @@
137
163
  $('#node-input-hueDevice').val(ui.item.hueDevice);
138
164
  }
139
165
  });
140
-
141
-
142
- // ########################
143
-
166
+ // ########################
144
167
 
145
168
  },
146
169
  oneditsave: function () {
@@ -163,7 +186,7 @@
163
186
  <br />
164
187
  <br />
165
188
  <p align="center">
166
- <i class="fal fa-star-and-crescent fa-8x"></i>
189
+ <i class="fa fa-star-and-crescent fa-bounce fa-8x"></i>
167
190
  </p>
168
191
  <br />
169
192
  <label for="node-input-server" >
@@ -188,7 +211,7 @@
188
211
 
189
212
  <div class="form-row">
190
213
  <label for="node-input-hueDevice" >
191
- <i class="fa fa-play-circle"></i>&nbspHue Sceme</label>
214
+ <i class="fa fa-play-circle"></i>&nbspHue Scene</label>
192
215
  <input type="text" id="node-input-name" placeholder="Enter your hue device name" />
193
216
  <input type="hidden" id="node-input-hueDevice" />
194
217
  </div>
@@ -205,23 +228,28 @@
205
228
 
206
229
  <br/>
207
230
 
231
+ <p>
232
+ <b>KNX</b>
208
233
  </p>
209
234
 
210
- <div class="form-row">
211
- <label for="node-input-namescene" style="width:100px;"><i class="fa fa-play-circle-o"></i> Scene</span></label>
235
+ <div class="form-row">
236
+ <label for="node-input-namescene" style="width:100px;"><i class="fa fa-play-circle-o"></i> Recall</label>
212
237
 
213
- <label for="node-input-GAscene" style="width:20px;">GA</label>
214
- <input type="text" id="node-input-GAscene" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
215
-
216
- <label for="node-input-dptscene" style="width:40px; margin-left: 0px; text-align: right;">DPT</label>
217
- <select id="node-input-dptscene" style="width:140px;"></select>
218
-
219
- <label for="node-input-namescene" style="width:50px; margin-left: 0px; text-align: right;">Name</label>
220
- <input type="text" id="node-input-namescene" style="width:200px;margin-left: 5px; text-align: left;">
221
- </div>
222
-
238
+ <label for="node-input-GAscene" style="width:20px;">GA</label>
239
+ <input type="text" id="node-input-GAscene" placeholder="Ex: 1/1/1" style="width:70px;margin-left: 5px; text-align: left;">
240
+
241
+ <label for="node-input-dptscene" style="width:40px; margin-left: 0px; text-align: right;">DPT</label>
242
+ <select id="node-input-dptscene" style="width:140px;"></select>
243
+
244
+ <label for="node-input-namescene" style="width:50px; margin-left: 0px; text-align: right;">Name</label>
245
+ <input type="text" id="node-input-namescene" style="width:200px;margin-left: 5px; text-align: left;">
246
+ </div>
247
+
248
+ <div class="form-row" id="divValScene" hidden>
249
+ <label for="node-input-valscene" style="width:100px;"></label>
250
+ <label for="node-input-valscene" style="width:20px;">#</label>
251
+ <select id="node-input-valscene" style="width:180px;margin-left: 5px; text-align: left;"></select>
223
252
  </div>
224
-
225
253
 
226
254
  <br/>
227
255
  <br/>
@@ -246,7 +274,8 @@ Start typing in the GA field, the name or group address of your KNX device, the
246
274
 
247
275
  |Property|Description|
248
276
  |--|--|
249
- | Scene | Choose your group address to be used for recalling the HUE scene. Send *true* to that group address to recall the scene, *false* to switch off all lights belonging to the scene. |
277
+ | Recall | Choose your group address to be used for recalling the HUE scene. In case of Datapoint 1.x, send *true* to that group address to recall the scene, *false* to switch off all lights belonging to the scene. |
278
+ | # | Select the KNX scene number. Visible only with datapoint 18.001. |
250
279
 
251
280
  <br/>
252
281
 
@@ -1,71 +1,78 @@
1
- const dptlib = require('./../KNXEngine/src/dptlib')
1
+ const dptlib = require('./../KNXEngine/src/dptlib');
2
2
 
3
3
  module.exports = function (RED) {
4
4
  function knxUltimateHueScene(config) {
5
- RED.nodes.createNode(this, config)
6
- const node = this
7
- node.server = RED.nodes.getNode(config.server)
8
- node.serverHue = RED.nodes.getNode(config.serverHue)
9
- node.topic = node.name
10
- node.name = config.name === undefined ? 'Hue' : config.name
11
- node.dpt = ''
12
- node.notifyreadrequest = false
13
- node.notifyreadrequestalsorespondtobus = 'false'
14
- node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = ''
15
- node.notifyresponse = false
16
- node.notifywrite = true
17
- node.initialread = true
18
- node.listenallga = true // Don't remove
19
- node.outputtype = 'write'
20
- node.outputRBE = false // Apply or not RBE to the output (Messages coming from flow)
21
- node.inputRBE = false // Apply or not RBE to the input (Messages coming from BUS)
22
- node.currentPayload = '' // Current value for the RBE input and for the .previouspayload msg
23
- node.passthrough = 'no'
24
- node.formatmultiplyvalue = 1
25
- node.formatnegativevalue = 'leave'
26
- node.formatdecimalsvalue = 2
5
+ RED.nodes.createNode(this, config);
6
+ const node = this;
7
+ node.server = RED.nodes.getNode(config.server);
8
+ node.serverHue = RED.nodes.getNode(config.serverHue);
9
+ node.topic = node.name;
10
+ node.name = config.name === undefined ? 'Hue' : config.name;
11
+ node.dpt = '';
12
+ node.notifyreadrequest = false;
13
+ node.notifyreadrequestalsorespondtobus = 'false';
14
+ node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = '';
15
+ node.notifyresponse = false;
16
+ node.notifywrite = true;
17
+ node.initialread = true;
18
+ node.listenallga = true; // Don't remove
19
+ node.outputtype = 'write';
20
+ node.outputRBE = false; // Apply or not RBE to the output (Messages coming from flow)
21
+ node.inputRBE = false; // Apply or not RBE to the input (Messages coming from BUS)
22
+ node.currentPayload = ''; // Current value for the RBE input and for the .previouspayload msg
23
+ node.passthrough = 'no';
24
+ node.formatmultiplyvalue = 1;
25
+ node.formatnegativevalue = 'leave';
26
+ node.formatdecimalsvalue = 2;
27
27
 
28
28
  // Used to call the status update from the config node.
29
29
  node.setNodeStatus = ({ fill, shape, text, payload }) => {
30
30
 
31
- }
31
+ };
32
32
  // Used to call the status update from the HUE config node.
33
33
  node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
34
- if (payload === undefined) return
35
- const dDate = new Date()
36
- payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
37
- node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
38
- }
34
+ if (payload === undefined) return;
35
+ const dDate = new Date();
36
+ payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString();
37
+ node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' });
38
+ };
39
39
 
40
40
  // This function is called by the knx-hue config node
41
41
  node.handleSend = msg => {
42
- let state = {}
42
+ let state = {};
43
43
  try {
44
44
  switch (msg.knx.destination) {
45
45
  case config.GAscene:
46
- msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptscene))
47
- if (msg.payload === true) {
48
- state = { recall: { action: config.hueSceneRecallType } }
49
- node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state, 'setScene')
46
+ msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptscene));
47
+ if (config.dptscene.startsWith("1.")) {
48
+ if (msg.payload === true) {
49
+ state = { recall: { action: config.hueSceneRecallType } };
50
+ node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state, 'setScene');
51
+ } else {
52
+ // Turn off all light belonging to the scene
53
+ (async () => {
54
+ try {
55
+ node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: false } }, 'stopScene');
56
+ } catch (error) {
57
+ RED.log.error('KNXUltimateHUEConfig: classHUE: handleQueue: stopScene: ' + error.message);
58
+ }
59
+ })();
60
+ }
50
61
  } else {
51
- // Turn off all light belonging to the scene
52
- (async () => {
53
- try {
54
- node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, { on: { on: false } }, 'stopScene')
55
- } catch (error) {
56
- console.log('KNXUltimateHUEConfig: classHUE: handleQueue: stopScene: ' + error.message)
57
- }
58
- })()
62
+ if (Number(config.valscene) === msg.payload.scenenumber && msg.payload.save_recall === 0) {
63
+ state = { recall: { action: config.hueSceneRecallType } };
64
+ node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, state, 'setScene');
65
+ }
59
66
  }
60
- node.setNodeStatusHue({ fill: 'green', shape: 'dot', text: 'KNX->HUE', payload: msg.payload })
61
- break
67
+ node.setNodeStatusHue({ fill: 'green', shape: 'dot', text: 'KNX->HUE', payload: msg.payload });
68
+ break;
62
69
  default:
63
- break
70
+ break;
64
71
  }
65
72
  } catch (error) {
66
- node.status({ fill: 'red', shape: 'dot', text: 'KNX->HUE error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
73
+ node.status({ fill: 'red', shape: 'dot', text: 'KNX->HUE error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' });
67
74
  }
68
- }
75
+ };
69
76
 
70
77
  node.handleSendHUE = _event => {
71
78
  try {
@@ -90,33 +97,33 @@ module.exports = function (RED) {
90
97
  // }
91
98
  }
92
99
  } catch (error) {
93
- node.status({ fill: 'red', shape: 'dot', text: 'HUE->KNX error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
100
+ node.status({ fill: 'red', shape: 'dot', text: 'HUE->KNX error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' });
94
101
  }
95
- }
102
+ };
96
103
 
97
104
  // On each deploy, unsubscribe+resubscribe
98
105
  if (node.server) {
99
- node.server.removeClient(node)
100
- node.server.addClient(node)
106
+ node.server.removeClient(node);
107
+ node.server.addClient(node);
101
108
  }
102
109
  if (node.serverHue) {
103
- node.serverHue.removeClient(node)
104
- node.serverHue.addClient(node)
110
+ node.serverHue.removeClient(node);
111
+ node.serverHue.addClient(node);
105
112
  }
106
113
 
107
114
  node.on('input', function (msg) {
108
115
 
109
- })
116
+ });
110
117
 
111
118
  node.on('close', function (done) {
112
119
  if (node.server) {
113
- node.server.removeClient(node)
120
+ node.server.removeClient(node);
114
121
  }
115
122
  if (node.serverHue) {
116
- node.serverHue.removeClient(node)
123
+ node.serverHue.removeClient(node);
117
124
  }
118
- done()
119
- })
125
+ done();
126
+ });
120
127
  }
121
- RED.nodes.registerType('knxUltimateHueScene', knxUltimateHueScene)
122
- }
128
+ RED.nodes.registerType('knxUltimateHueScene', knxUltimateHueScene);
129
+ };
@@ -196,6 +196,8 @@
196
196
 
197
197
  <br/>
198
198
 
199
+ <p>
200
+ <b>KNX</b>
199
201
  </p>
200
202
 
201
203
  <div class="form-row">
@@ -212,7 +214,7 @@
212
214
  </div>
213
215
 
214
216
 
215
- </div>
217
+
216
218
 
217
219
 
218
220
  <br/>
@@ -195,7 +195,7 @@
195
195
  <br/>
196
196
 
197
197
  <p>
198
- <b>PHILIPS HUE LIGHT EVENTS -> TO KNX</b>
198
+ <b>KNX</b>
199
199
  </p>
200
200
 
201
201
  <div class="form-row">
@@ -211,8 +211,6 @@
211
211
  <input type="text" id="node-input-nametemperaturesensor" style="width:200px;margin-left: 5px; text-align: left;">
212
212
  </div>
213
213
 
214
- </div>
215
-
216
214
 
217
215
  <br/>
218
216
  <br/>
@@ -235,7 +233,7 @@ Start typing in the GA field, the name or group address of your KNX device, the
235
233
  | HUE Bridge | Select the HUE Bridge to be used |
236
234
  | Hue Sensor | HUE sensor to be used. The avaiable buttons start showing up while you're typing.|
237
235
 
238
- **PHILIPS HUE LIGHT EVENTS -> TO KNX**
236
+ **KNX**
239
237
  |Property|Description|
240
238
  |--|--|
241
239
  | Temp | temperature value, in Celsius degrees |
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "engines": {
4
4
  "node": ">=16.0.0"
5
5
  },
6
- "version": "2.1.53",
6
+ "version": "2.1.55",
7
7
  "description": "Control your KNX intallation via Node-Red! Single Node KNX IN/OUT with optional ETS group address importer. Easy to use and highly configurable. With integrated Philips HUE devices handling.",
8
8
  "dependencies": {
9
9
  "binary-parser": "2.2.1",