node-red-contrib-knx-ultimate 2.2.2 → 2.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,6 +6,12 @@
6
6
 
7
7
  # CHANGELOG
8
8
 
9
+ <b>Version 2.2.4</b> - October 2023<br/>
10
+ - HUE Light: fixed some status hiccups and better handling of async hue bridge functions.<br/>
11
+ </p>
12
+ <b>Version 2.2.3</b> - October 2023<br/>
13
+ - HUE Light: Again, rewrite of the DIM function to get rid of the dimming_delta.<br/>
14
+ </p>
9
15
  <p>
10
16
  <b>Version 2.2.2</b> - October 2023<br/>
11
17
  - NEW: HUE Motion: support HUE Camera motion events via the HUE Motion node.<br/>
@@ -1,3 +1,5 @@
1
+ /* eslint-disable no-lonely-if */
2
+ /* eslint-disable no-param-reassign */
1
3
  /* eslint-disable no-inner-declarations */
2
4
  /* eslint-disable max-len */
3
5
  const dptlib = require("../KNXEngine/src/dptlib");
@@ -5,6 +7,12 @@ const HueClass = require("./utils/hueEngine").classHUE;
5
7
  const loggerEngine = require("./utils/sysLogger");
6
8
  const hueColorConverter = require("./utils/hueColorConverter");
7
9
 
10
+ function getRandomIntInclusive(min, max) {
11
+ min = Math.ceil(min);
12
+ max = Math.floor(max);
13
+ return Math.floor(Math.random() * (max - min + 1) + min); // The maximum is inclusive and the minimum is inclusive
14
+ }
15
+
8
16
  // Helpers
9
17
  const sortBy = (field) => (a, b) => {
10
18
  if (a[field] > b[field]) {
@@ -47,6 +55,7 @@ module.exports = (RED) => {
47
55
  const node = this;
48
56
  node.host = config.host;
49
57
  node.nodeClients = []; // Stores the registered clients
58
+ node.nodeClientsAwaitingInit = []; // Stores the nodes client to be initialized
50
59
  node.loglevel = config.loglevel !== undefined ? config.loglevel : "error"; // 18/02/2020 Loglevel default error
51
60
  node.sysLogger = null;
52
61
  node.hueAllResources = null;
@@ -85,67 +94,51 @@ module.exports = (RED) => {
85
94
  (async () => {
86
95
  try {
87
96
  await node.loadResourcesFromHUEBridge(); // Then, you can use node.getResources, that works locally and doesn't query the HUE Bridge.
88
- } catch (error) { /* empty */ }
97
+ } catch (error) {
98
+ /* empty */
99
+ }
89
100
  })();
90
101
  if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.info("node.hueManager connected event");
91
102
  });
92
103
  };
93
104
 
94
105
  // Query the HUE Bridge to return the resources
95
- node.loadResourcesFromHUEBridge = (_callerNode = undefined) => new Promise((resolve, reject) => {
106
+ node.loadResourcesFromHUEBridge = () => {
96
107
  (async () => {
97
108
  // °°°°°° Load ALL resources
98
109
  try {
99
- if (_callerNode === undefined) {
100
- node.hueAllResources = await node.hueManager.hueApiV2.get("/resource");
101
- node.hueAllRooms = node.hueAllResources.filter((a) => a.type === "room");
102
- // Update all KNX State of the nodes with the new hue device values
103
- node.nodeClients.forEach((nodeClient) => {
104
- if (nodeClient.hueDevice !== undefined) {
105
- const oHUEDevice = node.hueAllResources.filter((a) => a.id === nodeClient.hueDevice)[0];
106
- if (oHUEDevice !== undefined) {
107
- nodeClient.currentHUEDevice = oHUEDevice;
108
- for (const [key, value] of Object.entries(oHUEDevice)) {
109
- // Update KNX State
110
- const oProperty = { id: oHUEDevice.id };
111
- oProperty[key] = value;
112
- nodeClient.handleSendHUE(oProperty);
113
- }
114
- }
115
- }
110
+ node.hueAllResources = await node.hueManager.hueApiV2.get("/resource");
111
+ node.hueAllRooms = node.hueAllResources.filter((a) => a.type === "room");
112
+ // Update all KNX State of the nodes with the new hue device values
113
+ if (node.nodeClientsAwaitingInit !== undefined) {
114
+ // Because the whole process is async, if the function await node.hueManager.hueApiV2.get("/resource") has not jet been called or is late,
115
+ // the node/nodes belonging to this server, has been previously added to the nodeClientsAwaitingInit list.
116
+ node.nodeClientsAwaitingInit.forEach((nodeClient) => {
117
+ node.nodeClients.push(nodeClient);
116
118
  });
117
- } else {
118
- // °°°°°° Read ONE resource and update only one node. The node is requesting an update because it has been edited in Node-Red's window by the user
119
- try {
120
- // Please KEEP THE AWAIT, otherwise al posto dell'oggetto, a Promisse will be returned.
121
- const oHUEDevice = await node.hueAllResources.filter((a) => a.id === _callerNode.hueDevice)[0];
119
+ node.nodeClientsAwaitingInit = [];
120
+ }
121
+ node.nodeClients.forEach((nodeClient) => {
122
+ if (nodeClient.hueDevice !== undefined) {
123
+ const oHUEDevice = node.hueAllResources.filter((a) => a.id === nodeClient.hueDevice)[0];
122
124
  if (oHUEDevice !== undefined) {
123
- _callerNode.currentHUEDevice = oHUEDevice;
124
- for (const [key, value] of Object.entries(oHUEDevice)) {
125
- // Update KNX State
126
- const oProperty = { id: oHUEDevice.id };
127
- oProperty[key] = value;
128
- _callerNode.handleSendHUE(oProperty);
129
- }
130
- }
131
- } catch (error) {
132
- if (this.sysLogger !== undefined && this.sysLogger !== null) {
133
- this.sysLogger.error(`KNXUltimatehueEngine: loadResourcesFromHUEBridge, from a single node that has been edited: ${error.message}`);
134
- reject(error.message);
125
+ nodeClient.currentHUEDevice = oHUEDevice;
126
+ nodeClient.handleSendHUE(oHUEDevice);
135
127
  }
136
128
  }
137
- }
138
- resolve(true);
129
+ });
139
130
  } catch (error) {
140
131
  if (this.sysLogger !== undefined && this.sysLogger !== null) {
141
132
  this.sysLogger.error(`KNXUltimatehueEngine: loadResourcesFromHUEBridge: ${error.message}`);
142
- reject(error.message);
133
+ return (error.message);
143
134
  }
144
135
  }
136
+ return true;
145
137
  })();
146
- });
138
+ };
139
+
147
140
  // Returns the cached devices (node.hueAllResources) by type.
148
- node.getResources = (_rtype) => {
141
+ node.getResources = function getResources(_rtype) {
149
142
  try {
150
143
  if (node.hueAllResources === undefined) return;
151
144
  // Returns capitalized string
@@ -260,34 +253,43 @@ module.exports = (RED) => {
260
253
  };
261
254
 
262
255
  // Query HUE Bridge and get the updated color.
263
- node.getColorFromHueLight = (_lightId) => new Promise((resolve, reject) => {
264
- (async () => {
265
- try {
266
- // await node.loadResourcesFromHUEBridge();
267
- const oLight = node.hueAllResources.filter((a) => a.id === _lightId)[0];
268
- const ret = hueColorConverter.ColorConverter.xyBriToRgb(
269
- oLight.color.xy.x,
270
- oLight.color.xy.y,
271
- oLight.dimming.brightness,
272
- );
273
- resolve(JSON.stringify(ret));
274
- } catch (error) {
275
- if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`KNXUltimateHue: hueEngine: getColorFromHueLight: error ${error.message}`);
276
- reject(error.message);
277
- }
278
- })();
279
- });
256
+ node.getColorFromHueLight = (_lightId) => {
257
+ try {
258
+ // await node.loadResourcesFromHUEBridge();
259
+ const oLight = node.hueAllResources.filter((a) => a.id === _lightId)[0];
260
+ const ret = hueColorConverter.ColorConverter.xyBriToRgb(oLight.color.xy.x, oLight.color.xy.y, oLight.dimming.brightness);
261
+ return JSON.stringify(ret);
262
+ } catch (error) {
263
+ if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`KNXUltimateHue: hueEngine: getColorFromHueLight: error ${error.message}`);
264
+ return {};
265
+ }
266
+ };
280
267
 
281
268
  node.addClient = (_Node) => {
282
- // Check if node already exists
283
- if (node.nodeClients.filter((x) => x.id === _Node.id).length === 0) {
284
- // Add _Node to the clients array
285
- _Node.setNodeStatusHue({
286
- fill: "grey",
287
- shape: "ring",
288
- text: "Hue initialized.",
289
- });
290
- node.nodeClients.push(_Node);
269
+ // Update the node hue device, as soon as a node register itself to hue-config nodeClients
270
+ if (node.hueAllResources !== null) {
271
+ if (node.nodeClients.filter((x) => x.id === _Node.id).length === 0) { // At first start, due to the async method for retrieving hueAllResources, hueAllResources is still null. The first start is handled in node.hueManager.on("connected")
272
+ const oHUEDevice = node.hueAllResources.filter((a) => a.id === _Node.hueDevice)[0];
273
+ _Node.currentHUEDevice = oHUEDevice;
274
+ if (oHUEDevice !== undefined) _Node.handleSendHUE(oHUEDevice);
275
+ node.nodeClients.push(_Node);
276
+ // Add _Node to the clients array
277
+ _Node.setNodeStatusHue({
278
+ fill: "green",
279
+ shape: "ring",
280
+ text: "Ready",
281
+ });
282
+ }
283
+ } else {
284
+ if (node.nodeClientsAwaitingInit.filter((x) => x.id === _Node.id).length === 0) {
285
+ // Put the node in the waiting list
286
+ node.nodeClientsAwaitingInit.push(_Node);
287
+ _Node.setNodeStatusHue({
288
+ fill: "grey",
289
+ shape: "dot",
290
+ text: "Awaiting HUE Resources",
291
+ });
292
+ }
291
293
  }
292
294
  };
293
295
 
@@ -295,7 +297,9 @@ module.exports = (RED) => {
295
297
  // Remove the client node from the clients array
296
298
  try {
297
299
  node.nodeClients = node.nodeClients.filter((x) => x.id !== _Node.id);
298
- } catch (error) { /* empty */ }
300
+ } catch (error) {
301
+ /* empty */
302
+ }
299
303
  };
300
304
 
301
305
  node.on("close", (done) => {
@@ -320,14 +324,12 @@ module.exports = (RED) => {
320
324
  });
321
325
 
322
326
  RED.httpAdmin.get("/knxUltimateGetHueColor", RED.auth.needsPermission("hue-config.read"), (req, res) => {
323
- (async () => {
324
- try {
325
- const rgbColor = await node.getColorFromHueLight(req.query.id);
326
- res.json(rgbColor);
327
- } catch (error) {
328
- res.json("Select the device first!");
329
- }
330
- })();
327
+ try {
328
+ const rgbColor = node.getColorFromHueLight(req.query.id);
329
+ res.json(rgbColor);
330
+ } catch (error) {
331
+ res.json("Select the device first!");
332
+ }
331
333
  });
332
334
 
333
335
  RED.httpAdmin.get("/KNXUltimateGetResourcesHUE", RED.auth.needsPermission("hue-config.read"), (req, res) => {
@@ -347,8 +349,7 @@ module.exports = (RED) => {
347
349
  });
348
350
 
349
351
  RED.httpAdmin.get("/knxUltimateDpts", RED.auth.needsPermission("hue-config.read"), (req, res) => {
350
- const dpts = Object.entries(dptlib).filter(onlyDptKeys).map(extractBaseNo).sort(sortBy("base"))
351
- .reduce(toConcattedSubtypes, []);
352
+ const dpts = Object.entries(dptlib).filter(onlyDptKeys).map(extractBaseNo).sort(sortBy("base")).reduce(toConcattedSubtypes, []);
352
353
  res.json(dpts);
353
354
  });
354
355
  }
@@ -940,14 +940,16 @@ return msg;`,
940
940
  }
941
941
  // 12/11/2021 Starts the telegram out queue handler
942
942
  if (node.timerSendTelegramFromQueue !== null) clearInterval(node.timerSendTelegramFromQueue);
943
- node.timerSendTelegramFromQueue = setInterval(handleTelegramQueue, config.delaybetweentelegrams === undefined || Number(config.delaybetweentelegrams) < 20 ? 20 : Number(config.delaybetweentelegrams),
944
- ); // 02/01/2020 Start the timer that handles the queue of telegrams
943
+ node.timerSendTelegramFromQueue = setInterval(handleTelegramQueue, config.delaybetweentelegrams === undefined || Number(config.delaybetweentelegrams) < 20 ? 20 : Number(config.delaybetweentelegrams)); // 02/01/2020 Start the timer that handles the queue of telegrams
945
944
  node.linkStatus = "connected";
946
945
 
947
946
  // Start the timer to do initial read.
948
947
  if (node.timerDoInitialRead !== null) clearTimeout(node.timerDoInitialRead);
949
- node.timerDoInitialRead = setTimeout(DoInitialReadFromKNXBusOrFile, 6000); // 17/02/2020 Do initial read of all nodes requesting initial read
950
- node.timerCallConnectToHueBridgeOfAllHUEServers = setTimeout(callConnectToHueBridgeOfAllHUEServers, 10000); // connects all hue-config nodes to the HUE Bridge.
948
+ node.timerDoInitialRead = setTimeout(() => {
949
+ DoInitialReadFromKNXBusOrFile();
950
+ callConnectToHueBridgeOfAllHUEServers();
951
+ }, 6000); // 17/02/2020 Do initial read of all nodes requesting initial read
952
+ //node.timerCallConnectToHueBridgeOfAllHUEServers = setTimeout(callConnectToHueBridgeOfAllHUEServers, 6000); // connects all hue-config nodes to the HUE Bridge.
951
953
  const t = setTimeout(() => {
952
954
  // 21/03/2022 fixed possible memory leak. Previously was setTimeout without "let t = ".
953
955
  node.setAllClientsStatus("Connected.", "green", "On duty.");
@@ -1,107 +1,108 @@
1
1
  module.exports = function (RED) {
2
2
  function knxUltimateHueBattery(config) {
3
- RED.nodes.createNode(this, config)
4
- const node = this
5
- node.server = RED.nodes.getNode(config.server)
6
- node.serverHue = RED.nodes.getNode(config.serverHue)
7
- node.topic = node.name
8
- node.name = config.name === undefined ? 'Hue' : config.name
9
- node.dpt = ''
10
- node.notifyreadrequest = false
11
- node.notifyreadrequestalsorespondtobus = 'false'
12
- node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = ''
13
- node.notifyresponse = false
14
- node.notifywrite = true
15
- node.initialread = true
16
- node.listenallga = true // Don't remove
17
- node.outputtype = 'write'
18
- node.outputRBE = false // Apply or not RBE to the output (Messages coming from flow)
19
- node.inputRBE = false // Apply or not RBE to the input (Messages coming from BUS)
20
- node.currentPayload = '' // Current value for the RBE input and for the .previouspayload msg
21
- node.passthrough = 'no'
22
- node.formatmultiplyvalue = 1
23
- node.formatnegativevalue = 'leave'
24
- node.formatdecimalsvalue = 2
3
+ RED.nodes.createNode(this, config);
4
+ const node = this;
5
+ node.server = RED.nodes.getNode(config.server);
6
+ node.serverHue = RED.nodes.getNode(config.serverHue);
7
+ node.topic = node.name;
8
+ node.name = config.name === undefined ? 'Hue' : config.name;
9
+ node.dpt = '';
10
+ node.notifyreadrequest = false;
11
+ node.notifyreadrequestalsorespondtobus = 'false';
12
+ node.notifyreadrequestalsorespondtobusdefaultvalueifnotinitialized = '';
13
+ node.notifyresponse = false;
14
+ node.notifywrite = true;
15
+ node.initialread = true;
16
+ node.listenallga = true; // Don't remove
17
+ node.outputtype = 'write';
18
+ node.outputRBE = false; // Apply or not RBE to the output (Messages coming from flow)
19
+ node.inputRBE = false; // Apply or not RBE to the input (Messages coming from BUS)
20
+ node.currentPayload = ''; // Current value for the RBE input and for the .previouspayload msg
21
+ node.passthrough = 'no';
22
+ node.formatmultiplyvalue = 1;
23
+ node.formatnegativevalue = 'leave';
24
+ node.formatdecimalsvalue = 2;
25
25
 
26
26
  // Used to call the status update from the config node.
27
- node.setNodeStatus = ({ fill, shape, text, payload }) => {
27
+ node.setNodeStatus = ({
28
+ fill, shape, text, payload,
29
+ }) => {
28
30
 
29
- }
31
+ };
30
32
  // Used to call the status update from the HUE config node.
31
- node.setNodeStatusHue = ({ fill, shape, text, payload }) => {
32
- if (payload === undefined) return
33
- const dDate = new Date()
34
- payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString()
35
- node.status({ fill, shape, text: text + ' ' + payload + ' (' + dDate.getDate() + ', ' + dDate.toLocaleTimeString() + ')' })
36
- }
33
+ node.setNodeStatusHue = ({
34
+ fill, shape, text, payload,
35
+ }) => {
36
+ if (payload === undefined) payload = '';
37
+ const dDate = new Date();
38
+ payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString();
39
+ node.status({ fill, shape, text: `${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})` });
40
+ };
37
41
 
38
42
  // This function is called by the knx-ultimate config node, to output a msg.payload.
39
- node.handleSend = msg => {
40
- }
43
+ node.handleSend = (msg) => {
44
+ };
41
45
 
42
- node.handleSendHUE = _event => {
46
+ node.handleSendHUE = (_event) => {
43
47
  try {
44
48
  if (_event.id === config.hueDevice) {
45
- const knxMsgPayload = {}
46
- knxMsgPayload.topic = config.GAbatterysensor
47
- knxMsgPayload.dpt = config.dptbatterysensor
49
+ const knxMsgPayload = {};
50
+ knxMsgPayload.topic = config.GAbatterysensor;
51
+ knxMsgPayload.dpt = config.dptbatterysensor;
48
52
 
49
53
  if (_event.hasOwnProperty('power_state') && _event.power_state.hasOwnProperty('battery_level')) {
50
- knxMsgPayload.payload = _event.power_state.battery_level
54
+ knxMsgPayload.payload = _event.power_state.battery_level;
51
55
  // Send to KNX bus
52
- if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
53
-
56
+ if (knxMsgPayload.topic !== '' && knxMsgPayload.topic !== undefined) {
57
+ node.server.writeQueueAdd({
58
+ grpaddr: knxMsgPayload.topic, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id,
59
+ });
60
+ }
61
+
54
62
  // Setup the output msg
55
- knxMsgPayload.name = node.name
56
- knxMsgPayload.event = 'power_state'
63
+ knxMsgPayload.name = node.name;
64
+ knxMsgPayload.event = 'power_state';
57
65
 
58
66
  // Send payload
59
- knxMsgPayload.rawEvent = _event
60
- node.send(knxMsgPayload)
61
- node.setNodeStatusHue({ fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: knxMsgPayload.payload })
67
+ knxMsgPayload.rawEvent = _event;
68
+ node.send(knxMsgPayload);
69
+ node.setNodeStatusHue({
70
+ fill: 'blue', shape: 'ring', text: 'HUE->KNX', payload: knxMsgPayload.payload,
71
+ });
62
72
  }
63
73
  }
64
74
  } catch (error) {
65
- node.status({ fill: 'red', shape: 'dot', text: 'HUE->KNX error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
75
+ node.status({ fill: 'red', shape: 'dot', text: `HUE->KNX error ${error.message} (${new Date().getDate()}, ${new Date().toLocaleTimeString()})` });
66
76
  }
67
- }
77
+ };
68
78
 
69
79
  // On each deploy, unsubscribe+resubscribe
70
80
  if (node.server) {
71
- node.server.removeClient(node)
72
- node.server.addClient(node)
81
+ node.server.removeClient(node);
82
+ node.server.addClient(node);
73
83
  }
74
84
  if (node.serverHue) {
75
- node.serverHue.removeClient(node)
85
+ node.serverHue.removeClient(node);
76
86
  // I must get the object, to store read the battery status
77
87
  // I queue the state request, by passing the callback to call whenever the HUE bridge send me the light status async
78
88
  if (node.serverHue !== null && node.serverHue.hueManager !== null) {
79
- (async () => {
80
- try {
81
- node.serverHue.addClient(node)
82
- await node.serverHue.hueManager.writeHueQueueAdd(config.hueDevice, null, 'getBattery', (jLight) => {
83
- node.handleSendHUE(jLight)
84
- })
85
- } catch (err) {
86
- RED.log.error('Errore knxUltimateHueBattery subscribe: ' + err.message)
87
- }
88
- })()
89
+ node.serverHue.addClient(node);
89
90
  }
90
91
  }
91
92
 
92
- node.on('input', function (msg) {
93
+ node.on('input', (msg) => {
93
94
 
94
- })
95
+ });
95
96
 
96
- node.on('close', function (done) {
97
+ node.on('close', (done) => {
97
98
  if (node.server) {
98
- node.server.removeClient(node)
99
+ node.server.removeClient(node);
99
100
  }
100
101
  if (node.serverHue) {
101
- node.serverHue.removeClient(node)
102
+ node.serverHue.removeClient(node);
102
103
  }
103
- done()
104
- })
104
+ done();
105
+ });
105
106
  }
106
- RED.nodes.registerType('knxUltimateHueBattery', knxUltimateHueBattery)
107
- }
107
+ RED.nodes.registerType('knxUltimateHueBattery', knxUltimateHueBattery);
108
+ };
@@ -37,7 +37,7 @@ module.exports = function (RED) {
37
37
  node.setNodeStatusHue = ({
38
38
  fill, shape, text, payload,
39
39
  }) => {
40
- if (payload === undefined) return;
40
+ if (payload === undefined) payload = '';
41
41
  const dDate = new Date();
42
42
  payload = typeof payload === 'object' ? JSON.stringify(payload) : payload.toString();
43
43
  node.status({ fill, shape, text: `${text} ${payload} (${dDate.getDate()}, ${dDate.toLocaleTimeString()})` });
@@ -1,4 +1,24 @@
1
1
  <script type="text/javascript">
2
+ RED.events.on('nodes:add', function (node) {
3
+ if (node.type === 'uibuilder') {
4
+ // Keep a list of uib nodes in the editor
5
+ // may be different to the deployed list
6
+ editorInstances[node.id] = node.url
7
+ // -- IF uibuilderInstances <> editorInstances THEN there are undeployed instances. --
8
+ }
9
+ })
10
+ RED.events.on('nodes:change', function (node) {
11
+ if (node.type === 'uibuilder') {
12
+ mylog('nodes:change:', node)
13
+ editorInstances[node.id] = node.url
14
+ }
15
+ })
16
+ RED.events.on('nodes:remove', function (node) {
17
+ if (node.type === 'uibuilder') {
18
+ mylog('>> nodes:remove >>', node)
19
+ delete editorInstances[node.id]
20
+ }
21
+ })
2
22
  RED.nodes.registerType("knxUltimateHueLight", {
3
23
  category: "KNX Ultimate",
4
24
  color: "#C0C7E9",
@@ -66,7 +86,7 @@
66
86
  dptDaylightSensor: { value: "" },
67
87
 
68
88
  specifySwitchOnBrightness: { value: "yes" },
69
- updateKNXBrightnessStatusOnHUEOnOff: { value: "onhueoff" },
89
+ updateKNXBrightnessStatusOnHUEOnOff: { value: "no" },
70
90
  dimSpeed: { value: 5000, required: false },
71
91
  minDimLevelLight: { value: 10, required: false },
72
92
  maxDimLevelLight: { value: 100, required: false },
@@ -486,15 +506,15 @@
486
506
  $("#getColorAtSwitchOnNightTimeButton").text("Get current");
487
507
  });
488
508
  });
489
-
509
+
490
510
  // Fill options for minDimLevel and maxDimLevel
491
511
  for (let index = 0; index <= 90; index++) {
492
- if (index === 0){
512
+ if (index === 0) {
493
513
  $("#node-input-minDimLevelLight").append($("<option>").val(index).text(index.toString() + "% (Switch Off)"));
494
- }else{
514
+ } else {
495
515
  $("#node-input-minDimLevelLight").append($("<option>").val(index).text(index.toString() + "%"));
496
516
  }
497
-
517
+
498
518
  }
499
519
  $("#node-input-minDimLevelLight").val(node.minDimLevelLight);
500
520
  for (let index = 100; index >= 10; index--) {