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
|
-
-
|
|
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/>
|
package/nodes/hue-config.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
const dptlib = require('./../KNXEngine/src/dptlib')
|
|
3
|
-
const hueClass = require('./utils/
|
|
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
|
|
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
|
-
},
|
|
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,
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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",
|