node-red-contrib-knx-ultimate 2.1.36 → 2.1.38

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,9 +6,18 @@
6
6
 
7
7
  # CHANGELOG
8
8
 
9
+ <p>
10
+ <b>Version 2.1.38</b> - August 2023<br/>
11
+ - Strenghten HUE eventsource resiliency.<br/>
12
+ - Implemented standard logging on all HUE nodes (there was temporary console.log statements).<br/>
13
+ </p>
14
+ <p>
15
+ <b>Version 2.1.37</b> - July 2023<br/>
16
+ - Load control: added msg.shedding to force shed/unshed.<br/>
17
+ </p>
9
18
  <p>
10
19
  <b>Version 2.1.36</b> - July 2023<br/>
11
- - Bugfix: in some cases, the eventsource lost the connection while in idle for more than 15 minutes. Fixed.<br/>
20
+ - HUE Server bugfix: in some cases, the eventsource lost the connection while in idle for more than 15 minutes; fixed.<br/>
12
21
  </p>
13
22
  <p>
14
23
  <b>Version 2.1.35</b> - July 2023<br/>
@@ -1,6 +1,6 @@
1
1
 
2
2
  const dptlib = require('./../KNXEngine/src/dptlib')
3
- const hueClass = require('./utils/hueUtils').classHUE
3
+ const hueClass = require('./utils/hueEngine').classHUE
4
4
  const loggerEngine = require('./utils/sysLogger.js')
5
5
  // Helpers
6
6
  const sortBy = (field) => (a, b) => {
@@ -64,7 +64,7 @@ module.exports = (RED) => {
64
64
  node.name = (config.name === undefined || config.name === '') ? node.host : config.name // 12/08/2021
65
65
 
66
66
  // Init HUE Utility
67
- node.hueManager = new hueClass(node.host, node.credentials.username, node.credentials.clientkey, config.bridgeid)
67
+ node.hueManager = new hueClass(node.host, node.credentials.username, node.credentials.clientkey, config.bridgeid, node.sysLogger)
68
68
 
69
69
  // Event clip V2
70
70
  node.hueManager.on('event', _event => {
@@ -350,4 +350,75 @@
350
350
  </br>
351
351
  </br>
352
352
  </br>
353
- </script>
353
+ </script>
354
+
355
+
356
+ <script type="text/markdown" data-help-name="knxUltimateLoadControl">
357
+ <p>With the Load Control node you can automatically manage the disconnection of loads (washing machine, oven, etc.) when the current consumption exceeds a certain threshold.
358
+
359
+ The devices are turned off intelligently, checking the possible consumption of the device to determine whether to turn it off together with others. <br/>
360
+ The node can automatically reactivate the loads. <br/>
361
+ The node turns off one device (or multiple devices) at a time, based on the order you have selected.<br/>
362
+
363
+ **General**
364
+
365
+ |Property|Description|
366
+ |--|--|
367
+ | Gateway | KNX gateway. It is also possible not to select any gateway; in this case, only incoming messages to the node will be considered. |
368
+ | Monitor Wh | Group address representing the total consumption of your building. |
369
+ | Limit Wh | Maximum threshold that your electricity meter can withstand. When this threshold is exceeded, the node starts to turn off the devices. |
370
+ | Delay switch off (s) | Expressed in seconds, indicates how often the node will evaluate consumption and switch off each device. |
371
+ | Delay switch on (s) | Expressed in seconds, indicates how often the node will evaluate consumption and turn on each device that was turned off. |
372
+
373
+ <br/>
374
+
375
+ **LOAD CONTROL**
376
+
377
+ Here you can add devices to turn off in case of overload. <br/>
378
+ Choose the device to turn off. Enter the device name or its group address. <br/>
379
+ Enter any group address that indicates the consumption of the device chosen in the first line. ** This is an optional parameter **. If the device is consuming more than a certain number of Watts, it means that it is in use. If it consumes less, the device will be considered "not in use" and both this and the next will be turned off at once.<br/>
380
+ If *Automatic recovery* is enabled, the device is automatically reactivated when the "reset delay" expires.
381
+
382
+ ### Inputs
383
+
384
+ |Property|Description|
385
+ |--|--|
386
+ | `msg.readstatus = true` | Force the reading of the values from the KNX BUS of each device in the list. ***The node already does everything by itself***, but if necessary, it is possible to use this command to force a re-reading of the current values in watt.|
387
+ | `msg.enable = true` | Enable the load control.|
388
+ | `msg.disable = true` | Disable the load control.|
389
+ | `msg.reset = true` | Reset node states and turn all devices back on.|
390
+ | `msg.shedding` | String. *shed* to start the formward shedding sequence, *unshed* to start reverse shedding. Use this msg to force the shedding timer to start/stop, ignoring the **Monitor Wh** group address. Set *auto* to enable again the **Monitor Wh** group address monitoring. |
391
+
392
+
393
+ ### Outputs
394
+
395
+ 1. Standard output
396
+ : payload (string|object) : the standard output of the command.
397
+
398
+ ### Details
399
+
400
+ ```javascript
401
+
402
+ msg = {
403
+ "topic": "Home Total Consumption", // Node Name
404
+ "operation": "Increase Shedding" or "Decrease Shedding" or operation reflecting the input message (disable, enable, reset), // Operation
405
+ "device": "Washing machine", // Device shedded
406
+ "ga": "", // Group address of the shedded device
407
+ "totalPowerConsumption": 3100, // Current power consumption
408
+ "wattLimit": 3000, // Limit you set in the config window
409
+ "payload": 1, // Current shedding stage
410
+ }
411
+
412
+ ```
413
+
414
+ ### Sample
415
+
416
+ <a href="https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/SampleLoadControl">CLICK HERE FOR THE EXAMPLE</a>
417
+
418
+ <br/>
419
+
420
+ [Find it useful?](https://www.paypal.me/techtoday)
421
+
422
+ <br/>
423
+
424
+ </script>
@@ -1,6 +1,6 @@
1
1
 
2
2
  module.exports = function (RED) {
3
- function knxUltimateLoadControl (config) {
3
+ function knxUltimateLoadControl(config) {
4
4
  // const Address = require('./../KNXEngine/src/protocol/KNXAddress')
5
5
 
6
6
  RED.nodes.createNode(this, config)
@@ -169,7 +169,7 @@ module.exports = function (RED) {
169
169
  }
170
170
  }
171
171
  }
172
- }, 10000)
172
+ }, 20000)
173
173
  }
174
174
 
175
175
  // Start the timer
@@ -338,6 +338,25 @@ module.exports = function (RED) {
338
338
  if ((msg.hasOwnProperty('readstatus') && msg.readstatus === true)) {
339
339
  node.initialReadAllDevicesInRules()
340
340
  }
341
+
342
+ // 'shed', 'unshed', 'auto'
343
+ // | `msg.shedding` | String. *shed* to start the formward shedding sequence, *unshed* to start reverse shedding. Use this msg to force the shedding timer to start/stop, ignoring the **Monitor Wh** group address. Set *auto* to enable again the **Monitor Wh** group address monitoring. |
344
+ if (msg.shedding !== undefined) {
345
+ switch (msg.shedding) {
346
+ case 'shed':
347
+ node.wattLimit = 1 // Faking to shed
348
+ break;
349
+ case 'unshed':
350
+ node.wattLimit = 100000 // Faking to unshed
351
+ break;
352
+ case 'auto':
353
+ node.wattLimit = config.wattLimit === undefined ? 3000 : Number(config.wattLimit)
354
+ break;
355
+ default:
356
+ break;
357
+ }
358
+ }
359
+
341
360
  })
342
361
 
343
362
  node.on('close', function (done) {
@@ -5,19 +5,20 @@ const http = require('./http.js')
5
5
  const EventSource = require('eventsource');
6
6
 
7
7
  class classHUE extends EventEmitter {
8
- constructor(_hueBridgeIP, _username, _clientkey, _bridgeid) {
8
+ constructor(_hueBridgeIP, _username, _clientkey, _bridgeid, _sysLogger) {
9
9
  super()
10
- this.setup(_hueBridgeIP, _username, _clientkey, _bridgeid)
10
+ this.setup(_hueBridgeIP, _username, _clientkey, _bridgeid, _sysLogger)
11
11
  }
12
12
 
13
- setup = async (_hueBridgeIP, _username, _clientkey, _bridgeid) => {
13
+ setup = async (_hueBridgeIP, _username, _clientkey, _bridgeid, _sysLogger) => {
14
14
  this.hueBridgeIP = _hueBridgeIP
15
15
  this.username = _username
16
16
  this.clientkey = _clientkey
17
17
  this.bridgeid = _bridgeid
18
18
  this.commandQueue = []
19
19
  this.closePushEventStream = false
20
- this.timerwriteQueueAdd = setTimeout(this.handleQueue, 3000) // First start
20
+ this.timerwriteQueueAdd = setTimeout(this.handleQueue, 5000) // First start
21
+ this.sysLogger = _sysLogger
21
22
 
22
23
  // #############################################
23
24
  const options = {
@@ -25,8 +26,8 @@ class classHUE extends EventEmitter {
25
26
  'hue-application-key': this.username,
26
27
  },
27
28
  https: {
28
- rejectUnauthorized: false,
29
- },
29
+ rejectUnauthorized: false
30
+ }
30
31
  };
31
32
 
32
33
  // Connect
@@ -47,25 +48,21 @@ class classHUE extends EventEmitter {
47
48
  })
48
49
  }
49
50
  } catch (error) {
50
- console.log('KNXUltimateHUEUtils: classHUE: this.es.onmessage: ' + error.message)
51
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error('KNXUltimatehueEngine: classHUE: this.es.onmessage: ' + error.message)
51
52
  }
52
53
 
53
54
  };
54
55
 
55
56
  this.es.onopen = () => {
56
- //console.log('KNXUltimateHUEUtils: classHUE: SSE-Connected')
57
+ //if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error('KNXUltimatehueEngine: classHUE: SSE-Connected')
57
58
  //this.emit('connected');
58
59
  }
59
60
 
60
61
  this.es.onerror = (error) => {
61
62
  try {
62
- if (this.timerReconnect !== undefined) clearTimeout(this.timerReconnect)
63
- this.timerReconnect = setTimeout(() => {
64
- this.connect()
65
- }, 5000)
66
63
  this.es.close()
67
64
  this.es = null
68
- console.log('KNXUltimateHUEUtils: classHUE: request.on(error): ' + error.message)
65
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error('KNXUltimatehueEngine: classHUE: request.on(error): ' + error.message)
69
66
  } catch (error) {
70
67
  }
71
68
  //this.emit('error', err)
@@ -83,12 +80,20 @@ class classHUE extends EventEmitter {
83
80
  this.hueAllRooms = await this.hueApiV2.get('/resource/room')
84
81
  this.hueAllDevices = await this.hueApiV2.get('/resource/device')
85
82
  } catch (error) {
86
- if (this.timerReconnect !== undefined) clearTimeout(this.timerReconnect)
87
- this.timerReconnect = setTimeout(() => {
88
- this.connect()
89
- }, 5000)
90
- console.log('KNXUltimateHUEUtils: classHUE: this.hueApiV2 = await http.use: ' + error.message)
83
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error('KNXUltimatehueEngine: classHUE: this.hueApiV2 = await http.use: ' + error.message)
91
84
  }
85
+
86
+ // 31/07/2023 Every now and then, restart the connection to the eventsource, because it can goes down without knowing that
87
+ if (this.timerReconnect !== undefined) clearInterval(this.timerReconnect)
88
+ this.timerReconnect = setInterval(() => {
89
+ try {
90
+ this.es.close()
91
+ this.es = null
92
+ } catch (error) {
93
+ }
94
+ this.connect()
95
+ }, 120000)
96
+
92
97
  }
93
98
  // First connection
94
99
  this.connect()
@@ -108,14 +113,14 @@ class classHUE extends EventEmitter {
108
113
  try {
109
114
  const ok = await this.hueApiV2.put('/resource/light/' + jRet._lightID, jRet._state)
110
115
  } catch (error) {
111
- console.log('KNXUltimateHUEUtils: classHUE: handleQueue: setLight light: ' + error.message)
116
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.info('KNXUltimatehueEngine: classHUE: handleQueue: setLight light: ' + error.message)
112
117
  }
113
118
  break
114
119
  case 'setGroupedLight':
115
120
  try {
116
121
  const ok = await this.hueApiV2.put('/resource/grouped_light/' + jRet._lightID, jRet._state)
117
122
  } catch (error) {
118
- console.log('KNXUltimateHUEUtils: classHUE: handleQueue: setLight grouped_light: ' + error.message)
123
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.info('KNXUltimatehueEngine: classHUE: handleQueue: setLight grouped_light: ' + error.message)
119
124
  }
120
125
  break
121
126
  case 'getLight':
@@ -123,7 +128,7 @@ class classHUE extends EventEmitter {
123
128
  const jReturn = await this.hueApiV2.get('/resource/light/' + jRet._lightID)
124
129
  jRet._callback(jReturn[0]) // Need to call the callback, because the event is absolutely async
125
130
  } catch (error) {
126
- console.log('KNXUltimateHUEUtils: classHUE: handleQueue: getLight light: ' + error.message)
131
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.info('KNXUltimatehueEngine: classHUE: handleQueue: getLight light: ' + error.message)
127
132
  }
128
133
  break
129
134
  case 'getGroupedLight':
@@ -131,7 +136,7 @@ class classHUE extends EventEmitter {
131
136
  const jReturn = await this.hueApiV2.get('/resource/grouped_light/' + jRet._lightID)
132
137
  jRet._callback(jReturn[0]) // Need to call the callback, because the event is absolutely async
133
138
  } catch (error) {
134
- console.log('KNXUltimateHUEUtils: classHUE: handleQueue: getLight grouped_light: ' + error.message)
139
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.info('KNXUltimatehueEngine: classHUE: handleQueue: getLight grouped_light: ' + error.message)
135
140
  }
136
141
  break
137
142
  case 'setScene':
@@ -139,7 +144,7 @@ class classHUE extends EventEmitter {
139
144
  const sceneID = jRet._lightID
140
145
  const ok = await this.hueApiV2.put('/resource/scene/' + sceneID, jRet._state)
141
146
  } catch (error) {
142
- console.log('KNXUltimateHUEUtils: classHUE: handleQueue: setScene: ' + error.message)
147
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.info('KNXUltimatehueEngine: classHUE: handleQueue: setScene: ' + error.message)
143
148
  }
144
149
  break
145
150
  case 'stopScene':
@@ -152,7 +157,7 @@ class classHUE extends EventEmitter {
152
157
  this.writeHueQueueAdd(light.rid, jRet._state, 'setLight')
153
158
  });
154
159
  } catch (error) {
155
- console.log('KNXUltimateHUEUtils: classHUE: handleQueue: stopScene: ' + error.message)
160
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error('KNXUltimatehueEngine: classHUE: handleQueue: stopScene: ' + error.message)
156
161
  }
157
162
  break
158
163
  case 'getBattery':
@@ -160,14 +165,14 @@ class classHUE extends EventEmitter {
160
165
  const jReturn = await this.hueApiV2.get('/resource/device_power/' + jRet._lightID)
161
166
  jRet._callback(jReturn[0]) // Need to call the callback, because the event is absolutely async
162
167
  } catch (error) {
163
- console.log('KNXUltimateHUEUtils: classHUE: handleQueue: getBattery: ' + error.message)
168
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error('KNXUltimatehueEngine: classHUE: handleQueue: getBattery: ' + error.message)
164
169
  }
165
170
  case 'getLightLevel':
166
171
  try {
167
172
  const jReturn = await this.hueApiV2.get('/resource/light_level/' + jRet._lightID)
168
173
  jRet._callback(jReturn[0]) // Need to call the callback, because the event is absolutely async
169
174
  } catch (error) {
170
- console.log('KNXUltimateHUEUtils: classHUE: handleQueue: getLightLevel: ' + error.message)
175
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error('KNXUltimatehueEngine: classHUE: handleQueue: getLightLevel: ' + error.message)
171
176
  }
172
177
  break
173
178
  case 'getTemperature':
@@ -175,7 +180,7 @@ class classHUE extends EventEmitter {
175
180
  const jReturn = await this.hueApiV2.get('/resource/temperature/' + jRet._lightID)
176
181
  jRet._callback(jReturn[0]) // Need to call the callback, because the event is absolutely async
177
182
  } catch (error) {
178
- console.log('KNXUltimateHUEUtils: classHUE: handleQueue: getTemperature: ' + error.message)
183
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error('KNXUltimatehueEngine: classHUE: handleQueue: getTemperature: ' + error.message)
179
184
  }
180
185
  break
181
186
  default:
@@ -274,7 +279,7 @@ class classHUE extends EventEmitter {
274
279
  }
275
280
  return { devices: retArray }
276
281
  } catch (error) {
277
- console.log('KNXUltimateHue: HueUtils: classHUE: getDevices: error ' + error.message)
282
+ if (this.sysLogger !== undefined && this.sysLogger !== null) this.sysLogger.error('KNXUltimateHue: hueEngine: classHUE: getDevices: error ' + error.message)
278
283
  return ({ devices: error.message })
279
284
  }
280
285
  }
@@ -282,6 +287,7 @@ class classHUE extends EventEmitter {
282
287
  close = async () => {
283
288
  return new Promise((resolve, reject) => {
284
289
  try {
290
+ if (this.timerReconnect !== undefined) clearInterval(this.timerReconnect)
285
291
  this.closePushEventStream = true
286
292
  if (this.es !== null) this.es.close();
287
293
  this.es = null;
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "engines": {
4
4
  "node": ">=16.0.0"
5
5
  },
6
- "version": "2.1.36",
6
+ "version": "2.1.38",
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
  "mkdirp": "3.0.1",