node-red-contrib-knx-ultimate 2.1.63 → 2.2.1

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,13 @@
6
6
 
7
7
  # CHANGELOG
8
8
  <p>
9
+ <b>Version 2.2.1</b> - October 2023<br/>
10
+ - Massive rewrite of the DIM function, for brightness and for color temperature.<br/>
11
+ - NEW: HUE Light: Added dimming speed, minimum dim value and maximum dim value.<br/>
12
+ - NEW: HUE Light: Read of the lamp status at node-red start and after deploy of a new node.<br/>
13
+ - Security fix: patched a vulnerability in crypto.js.<br/>
14
+ </p>
15
+ <p>
9
16
  <b>Version 2.1.63</b> - October 2023<br/>
10
17
  - HUE Light: optimized the GUI in select color TAB.<br/>
11
18
  </p>
@@ -44,7 +44,7 @@
44
44
  "log-driver": "1.2.7",
45
45
  "lodash": "4.17.21",
46
46
  "path": "0.12.7",
47
- "crypto-js": "4.1.1",
47
+ "crypto-js": "4.2.0",
48
48
  "xml2js": "0.6.0"
49
49
  },
50
50
  "devDependencies": {}
@@ -129,8 +129,8 @@
129
129
 
130
130
 
131
131
  </script>
132
- <script type="text/markdown" data-help-name="hue-config">
133
- <p> This node registers to the Hue Bridge.<br/>
132
+ <script type="text/markdown" data-help-name="hue-config"
133
+ This node registers to the Hue Bridge.
134
134
 
135
135
  Just set the Bridge's IP and click **CONNECT** button.
136
136
 
@@ -35,12 +35,13 @@ const toConcattedSubtypes = (acc, baseType) => {
35
35
  return acc.concat(subtypes);
36
36
  };
37
37
 
38
- module.exports = (RED) => {
39
- RED.httpAdmin.get("/knxUltimateDpts", RED.auth.needsPermission("hue-config.read"), (req, res) => {
40
- const dpts = Object.entries(dptlib).filter(onlyDptKeys).map(extractBaseNo).sort(sortBy("base")).reduce(toConcattedSubtypes, []);
41
- res.json(dpts);
42
- });
38
+ function getRandomInt(min, max) {
39
+ min = Math.ceil(min);
40
+ max = Math.floor(max);
41
+ return Math.floor(Math.random() * (max - min) + min); // The maximum is exclusive and the minimum is inclusive
42
+ }
43
43
 
44
+ module.exports = (RED) => {
44
45
  function hueConfig(config) {
45
46
  RED.nodes.createNode(this, config);
46
47
  const node = this;
@@ -48,6 +49,7 @@ module.exports = (RED) => {
48
49
  node.nodeClients = []; // Stores the registered clients
49
50
  node.loglevel = config.loglevel !== undefined ? config.loglevel : "error"; // 18/02/2020 Loglevel default error
50
51
  node.sysLogger = null;
52
+ node.hueAllResources = null;
51
53
  try {
52
54
  node.sysLogger = loggerEngine.get({ loglevel: node.loglevel }); // New logger to adhere to the loglevel selected in the config-window
53
55
  } catch (error) {
@@ -80,20 +82,72 @@ module.exports = (RED) => {
80
82
  });
81
83
  // Connected
82
84
  node.hueManager.on("connected", () => {
85
+ (async () => {
86
+ try {
87
+ await node.loadResourcesFromHUEBridge(); // Then, you can use node.getResources, that works locally and doesn't query the HUE Bridge.
88
+ } catch (error) { /* empty */ }
89
+ })();
83
90
  if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.info("node.hueManager connected event");
84
91
  });
85
- // Initialize the http wrapper, to use the provided key.
86
- // This http wrapper is used to get the data from HUE brigde
87
- await node.refreshResources();
88
92
  };
89
93
 
90
- (async () => {
91
- await node.ConnectToHueBridge();
92
- })();
93
-
94
- // Get all devices and join it with relative rooms, by adding the room name to the device name
94
+ // Query the HUE Bridge to return the resources
95
+ node.loadResourcesFromHUEBridge = (_callerNode = undefined) => new Promise((resolve, reject) => {
96
+ (async () => {
97
+ // Reload all resources
98
+ 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
+ let oProperty = { id: oHUEDevice.id }
111
+ oProperty[key] = value;
112
+ nodeClient.handleSendHUE(oProperty);
113
+ }
114
+ }
115
+ }
116
+ });
117
+ } else {
118
+ // Update only one node. The node is requesting an update because it has beeb edited 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];
122
+ if (oHUEDevice !== undefined) {
123
+ _callerNode.currentHUEDevice = oHUEDevice;
124
+ for (const [key, value] of Object.entries(oHUEDevice)) {
125
+ // Update KNX State
126
+ let 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);
135
+ }
136
+ }
137
+ }
138
+ resolve(true);
139
+ } catch (error) {
140
+ if (this.sysLogger !== undefined && this.sysLogger !== null) {
141
+ this.sysLogger.error(`KNXUltimatehueEngine: loadResourcesFromHUEBridge: ${error.message}`);
142
+ reject(error.message);
143
+ }
144
+ }
145
+ })();
146
+ });
147
+ // Returns the cached devices (node.hueAllResources) by type.
95
148
  node.getResources = (_rtype) => {
96
149
  try {
150
+ if (node.hueAllResources === undefined) return;
97
151
  // Returns capitalized string
98
152
  function capStr(s) {
99
153
  if (typeof s !== "string") return "";
@@ -200,32 +254,16 @@ module.exports = (RED) => {
200
254
  }
201
255
  return { devices: retArray };
202
256
  } catch (error) {
203
- if (node.sysLogger !== undefined && node.sysLogger !== null)
204
- node.sysLogger.error(`KNXUltimateHue: hueEngine: classHUE: getDevices: error ${error.message}`);
257
+ if (node.sysLogger !== undefined && node.sysLogger !== null) node.sysLogger.error(`KNXUltimateHue: hueEngine: classHUE: getResources: error ${error.message}`);
205
258
  return { devices: error.message };
206
259
  }
207
260
  };
208
- node.refreshResources = () => new Promise((resolve, reject) => {
209
- (async () => {
210
- // Reload all resources
211
- try {
212
- node.hueAllResources = await node.hueManager.hueApiV2.get("/resource");
213
- node.hueAllRooms = node.hueAllResources.filter((a) => a.type === "room");
214
- resolve(true);
215
- } catch (error) {
216
- if (this.sysLogger !== undefined && this.sysLogger !== null) {
217
- this.sysLogger.error(`KNXUltimatehueEngine: getting resources: ${error.message}`);
218
- reject(error.message);
219
- }
220
- }
221
- })();
222
- });
223
261
 
224
- // Get all devices and join it with relative rooms, by adding the room name to the device name
262
+ // Query HUE Bridge and get the updated color.
225
263
  node.getColorFromHueLight = (_lightId) => new Promise((resolve, reject) => {
226
264
  (async () => {
227
265
  try {
228
- await node.refreshResources();
266
+ // await node.loadResourcesFromHUEBridge();
229
267
  const oLight = node.hueAllResources.filter((a) => a.id === _lightId)[0];
230
268
  const ret = hueColorConverter.ColorConverter.xyBriToRgb(
231
269
  oLight.color.xy.x,
@@ -307,9 +345,12 @@ module.exports = (RED) => {
307
345
  })();
308
346
  }
309
347
  });
310
- }
311
348
 
312
- // RED.nodes.registerType("hue-config", hue-config);
349
+ 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")).reduce(toConcattedSubtypes, []);
351
+ res.json(dpts);
352
+ });
353
+ }
313
354
  RED.nodes.registerType("hue-config", hueConfig, {
314
355
  credentials: {
315
356
  username: { type: "password" },