node-red-contrib-knx-ultimate 2.0.0 → 2.0.2

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.
Files changed (40) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/KNXEngine/dptlib/index.js +1 -1
  3. package/KNXUltimate.code-workspace +11 -1
  4. package/README.md +1 -1
  5. package/img/hue.png +0 -0
  6. package/img/hueButton.png +0 -0
  7. package/img/hueLight.png +0 -0
  8. package/img/knx.png +0 -0
  9. package/nodes/hue-config.js +20 -6
  10. package/nodes/knxUltimateHueButton.html +586 -0
  11. package/nodes/knxUltimateHueButton.js +159 -0
  12. package/nodes/knxUltimateHueLight.html +363 -55
  13. package/nodes/knxUltimateHueLight.js +70 -13
  14. package/nodes/locales/en-US/knxUltimateHueLight.json +3 -3
  15. package/nodes/utils/hueColorConverter.js +237 -0
  16. package/nodes/utils/hueUtils.js +37 -21
  17. package/package.json +6 -4
  18. package/nodes/locales/en-US/knxUltimateHueLight.html +0 -10
  19. /package/nodes/locales/{de → de-disabled}/hue-config.html +0 -0
  20. /package/nodes/locales/{de → de-disabled}/hue-config.json +0 -0
  21. /package/nodes/locales/{de → de-disabled}/knxUltimate-config.html +0 -0
  22. /package/nodes/locales/{de → de-disabled}/knxUltimate-config.json +0 -0
  23. /package/nodes/locales/{de → de-disabled}/knxUltimate.html +0 -0
  24. /package/nodes/locales/{de → de-disabled}/knxUltimate.json +0 -0
  25. /package/nodes/locales/{de → de-disabled}/knxUltimateAlerter.html +0 -0
  26. /package/nodes/locales/{de → de-disabled}/knxUltimateAlerter.json +0 -0
  27. /package/nodes/locales/{de → de-disabled}/knxUltimateGlobalContext.html +0 -0
  28. /package/nodes/locales/{de → de-disabled}/knxUltimateGlobalContext.json +0 -0
  29. /package/nodes/locales/{de → de-disabled}/knxUltimateHueLight.html +0 -0
  30. /package/nodes/locales/{de → de-disabled}/knxUltimateHueLight.json +0 -0
  31. /package/nodes/locales/{de → de-disabled}/knxUltimateLoadControl.html +0 -0
  32. /package/nodes/locales/{de → de-disabled}/knxUltimateLoadControl.json +0 -0
  33. /package/nodes/locales/{de → de-disabled}/knxUltimateLogger.html +0 -0
  34. /package/nodes/locales/{de → de-disabled}/knxUltimateLogger.json +0 -0
  35. /package/nodes/locales/{de → de-disabled}/knxUltimateSceneController.html +0 -0
  36. /package/nodes/locales/{de → de-disabled}/knxUltimateSceneController.json +0 -0
  37. /package/nodes/locales/{de → de-disabled}/knxUltimateViewer.html +0 -0
  38. /package/nodes/locales/{de → de-disabled}/knxUltimateViewer.json +0 -0
  39. /package/nodes/locales/{de → de-disabled}/knxUltimateWatchDog.html +0 -0
  40. /package/nodes/locales/{de → de-disabled}/knxUltimateWatchDog.json +0 -0
@@ -1,7 +1,23 @@
1
1
  module.exports = function (RED) {
2
2
  const dptlib = require('./../KNXEngine/dptlib')
3
+ const hueColorConverter = require('./utils/hueColorConverter')
3
4
 
4
5
 
6
+ async function getLightState(node, _lightID) {
7
+ return new Promise((resolve, reject) => {
8
+ try {
9
+ if (node !== null && node.serverHue !== null && node.serverHue.hueManager !== null) {
10
+ node.serverHue.hueManager.getLight(_lightID).then(ret => {
11
+ node.currentHUEDevice = ret[0]
12
+ resolve(ret)
13
+ })
14
+ }
15
+ } catch (error) {
16
+ reject(error)
17
+ }
18
+ })
19
+ }
20
+
5
21
  function knxUltimateHueLight(config) {
6
22
  RED.nodes.createNode(this, config)
7
23
  const node = this
@@ -27,6 +43,16 @@ module.exports = function (RED) {
27
43
  node.formatnegativevalue = 'leave'
28
44
  node.formatdecimalsvalue = 2
29
45
 
46
+
47
+
48
+ // Read the state of the light and store it in the holding object
49
+ try {
50
+ if (config.hueDevice !== undefined && config.hueDevice !== '') getLightState(node, config.hueDevice)
51
+ } catch (error) {
52
+ }
53
+
54
+
55
+
30
56
  // Used to call the status update from the config node.
31
57
  node.setNodeStatus = ({ fill, shape, text, payload }) => {
32
58
 
@@ -34,38 +60,69 @@ module.exports = function (RED) {
34
60
 
35
61
  // This function is called by the knx-ultimate config node, to output a msg.payload.
36
62
  node.handleSend = msg => {
37
- let state
63
+ let state = {}
38
64
  try {
39
65
  switch (msg.knx.destination) {
40
66
  case config.GALightSwitch:
41
67
  msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightSwitch))
42
68
  state = msg.payload === true ? { on: { on: true } } : { on: { on: false } }
43
- node.serverHue.setLightState(config.hueLight.split('#')[1], state)
69
+ node.serverHue.hueManager.setLightState(config.hueDevice, state)
44
70
  break
45
71
  case config.GALightDIM:
46
72
  msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightDIM))
47
73
  state = msg.payload.decr_incr === 1 ? { dimming_delta: { action: 'up', brightness_delta: 20 } } : { dimming_delta: { action: 'down', brightness_delta: 20 } }
48
- node.serverHue.setLightState(config.hueLight.split('#')[1], state)
74
+ node.serverHue.hueManager.setLightState(config.hueDevice, state)
75
+ break
76
+ case config.GALightBrightness:
77
+ msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightBrightness))
78
+ state = { dimming: { brightness: msg.payload } }
79
+ node.serverHue.hueManager.setLightState(config.hueDevice, state)
80
+ break
81
+ case config.GALightColor:
82
+ // Behavior like ISE HUE CONNECT, by setting the brightness and on/off as well
83
+ msg.payload = dptlib.fromBuffer(msg.knx.rawValue, dptlib.resolve(config.dptLightColor))
84
+ const gamut = node.currentHUEDevice.color.gamut_type || null
85
+ const retXY = hueColorConverter.ColorConverter.rgbToXy(msg.payload.red, msg.payload.green, msg.payload.blue, gamut)
86
+ const bright = hueColorConverter.ColorConverter.getBrightnessFromRGB(msg.payload.red, msg.payload.green, msg.payload.blue)
87
+ bright > 0 ? state = { on: { on: true }, dimming: { brightness: bright }, color: { xy: retXY } } : state = { on: { on: false } }
88
+ node.serverHue.hueManager.setLightState(config.hueDevice, state)
49
89
  break
50
90
  default:
51
91
  break
52
92
  }
53
93
  } catch (error) {
54
-
94
+ node.status({ fill: 'red', shape: 'dot', text: 'KNX->HUE error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
55
95
  }
56
- //node.exposedGAs.push({ address: msg.knx.destination, addressRAW: sAddressRAW, dpt: msg.knx.dpt, payload: msg.payload, devicename: sDeviceName, lastupdate: new Date(), rawPayload: 'HEX Raw: ' + msg.knx.rawValue.toString('hex') || '?', payloadmeasureunit: (msg.payloadmeasureunit !== 'unknown' ? ' ' + msg.payloadmeasureunit : '') })
96
+ // node.exposedGAs.push({ address: msg.knx.destination, addressRAW: sAddressRAW, dpt: msg.knx.dpt, payload: msg.payload, devicename: sDeviceName, lastupdate: new Date(), rawPayload: 'HEX Raw: ' + msg.knx.rawValue.toString('hex') || '?', payloadmeasureunit: (msg.payloadmeasureunit !== 'unknown' ? ' ' + msg.payloadmeasureunit : '') })
57
97
  }
58
98
 
59
-
60
99
  node.handleSendHUE = _event => {
61
- if (_event.id === config.hueLight.split('#')[1]) {
62
- let knxMsgPayload = undefined
63
- if (_event.hasOwnProperty('on')) knxMsgPayload = _event.on.on
64
- // Send to KNX bus
65
- if (knxMsgPayload !== undefined) {
66
- node.status({ fill: 'green', shape: 'dot', text: 'HUE Status ' + knxMsgPayload + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
67
- if (config.GALightState !== '') node.server.writeQueueAdd({ grpaddr: config.GALightState, payload: knxMsgPayload, dpt: config.dptLightState, outputtype: 'write', nodecallerid: node.id })
100
+ try {
101
+ if (_event.id === config.hueDevice) {
102
+ let knxMsgPayload = {}
103
+ if (_event.hasOwnProperty('on')) {
104
+ knxMsgPayload.ga = config.GALightState
105
+ knxMsgPayload.dpt = config.dptLightState
106
+ knxMsgPayload.payload = _event.on.on
107
+ }
108
+ if (_event.hasOwnProperty('color')) {
109
+ knxMsgPayload.ga = config.GALightColorState
110
+ knxMsgPayload.dpt = config.dptLightColorState
111
+ knxMsgPayload.payload = hueColorConverter.ColorConverter.xyBriToRgb(_event.color.xy.x, _event.color.xy.y, node.currentHUEDevice.dimming.brightness)
112
+ }
113
+ if (_event.hasOwnProperty('dimming')) {
114
+ knxMsgPayload.ga = config.GALightBrightnessState
115
+ knxMsgPayload.dpt = config.dptLightBrightnessState
116
+ knxMsgPayload.payload = _event.dimming.brightness
117
+ }
118
+ // Send to KNX bus
119
+ if (knxMsgPayload.ga !== undefined) {
120
+ node.status({ fill: 'green', shape: 'dot', text: 'HUE->KNX State ' + JSON.stringify(knxMsgPayload.payload) + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
121
+ if (knxMsgPayload.ga !== '' && knxMsgPayload.ga !== undefined) node.server.writeQueueAdd({ grpaddr: knxMsgPayload.ga, payload: knxMsgPayload.payload, dpt: knxMsgPayload.dpt, outputtype: 'write', nodecallerid: node.id })
122
+ }
68
123
  }
124
+ } catch (error) {
125
+ node.status({ fill: 'red', shape: 'dot', text: 'HUE->KNX error ' + error.message + ' (' + new Date().getDate() + ', ' + new Date().toLocaleTimeString() + ')' })
69
126
  }
70
127
  }
71
128
 
@@ -3,12 +3,12 @@
3
3
  "helplink": "&nbsp<i class=\"fa fa-question-circle\"></i>&nbsp<a target=\"_blank\" href=\"https://github.com/Supergiovane/node-red-contrib-knx-ultimate/wiki/en-hue-configuration\"><u>Configuration</u></a>",
4
4
  "title": "HUE node",
5
5
  "node-input-name": "Name",
6
- "node-input-nameLightSwitch": "Switch (bit)",
6
+ "node-input-nameLightSwitch": "Switch",
7
7
  "node-input-GALightSwitch": "GA",
8
8
  "node-input-dptLightSwitch": "dpt",
9
- "node-input-nameLightState": "State (bit)",
9
+ "node-input-nameLightState": "Switch State",
10
10
  "node-input-GALightState": "GA",
11
11
  "node-input-dptLightState": "dpt",
12
- "node-input-hueLight": "HUE light"
12
+ "node-input-hueLight": "HUE Light"
13
13
  }
14
14
  }
@@ -0,0 +1,237 @@
1
+ const convert = require('color-convert')
2
+ class ColorConverter {
3
+ static getGamutRanges() {
4
+ const gamutA = {
5
+ red: [0.704, 0.296],
6
+ green: [0.2151, 0.7106],
7
+ blue: [0.138, 0.08]
8
+ }
9
+
10
+ const gamutB = {
11
+ red: [0.675, 0.322],
12
+ green: [0.409, 0.518],
13
+ blue: [0.167, 0.04]
14
+ }
15
+
16
+ const gamutC = {
17
+ red: [0.692, 0.308],
18
+ green: [0.17, 0.7],
19
+ blue: [0.153, 0.048]
20
+ }
21
+
22
+ const defaultGamut = {
23
+ red: [1.0, 0],
24
+ green: [0.0, 1.0],
25
+ blue: [0.0, 0.0]
26
+ }
27
+
28
+ return { gamutA, gamutB, gamutC, default: defaultGamut }
29
+ }
30
+
31
+ static getLightColorGamutRange(gamutTypeABC = null) {
32
+ const ranges = ColorConverter.getGamutRanges()
33
+ const gamutA = ranges.gamutA
34
+ const gamutB = ranges.gamutB
35
+ const gamutC = ranges.gamutC
36
+
37
+ const philipsModels = {
38
+ A: gamutA,
39
+ B: gamutB,
40
+ C: gamutC
41
+ }
42
+
43
+ if (philipsModels[gamutTypeABC]) {
44
+ return philipsModels[gamutTypeABC]
45
+ }
46
+
47
+ return ranges.default
48
+ }
49
+
50
+ static rgbToXy(red, green, blue, gamutTypeABC = null) {
51
+ function getGammaCorrectedValue(value) {
52
+ return (value > 0.04045) ? Math.pow((value + 0.055) / (1.0 + 0.055), 2.4) : (value / 12.92)
53
+ }
54
+
55
+ const colorGamut = ColorConverter.getLightColorGamutRange(gamutTypeABC)
56
+
57
+ red = parseFloat(red / 255)
58
+ green = parseFloat(green / 255)
59
+ blue = parseFloat(blue / 255)
60
+
61
+ red = getGammaCorrectedValue(red)
62
+ green = getGammaCorrectedValue(green)
63
+ blue = getGammaCorrectedValue(blue)
64
+
65
+ const x = red * 0.649926 + green * 0.103455 + blue * 0.197109
66
+ const y = red * 0.234327 + green * 0.743075 + blue * 0.022598
67
+ const z = red * 0.0000000 + green * 0.053077 + blue * 1.035763
68
+
69
+ let xy = {
70
+ x: x / (x + y + z),
71
+ y: y / (x + y + z)
72
+ }
73
+
74
+ if (!ColorConverter.xyIsInGamutRange(xy, colorGamut)) {
75
+ xy = ColorConverter.getClosestColor(xy, colorGamut)
76
+ }
77
+
78
+ return xy
79
+ }
80
+
81
+ static getBrightnessFromRGB(red, green, blue) {
82
+ const hsv = convert.rgb.hsv(red, green, blue)
83
+ const brightness = hsv[2]
84
+ return brightness
85
+ }
86
+
87
+ static convert_1_255_ToPercentage(number) {
88
+ const percentage = (number / 255) * 100
89
+ return percentage
90
+ }
91
+
92
+ static xyIsInGamutRange(xy, gamut) {
93
+ gamut = gamut || ColorConverter.getGamutRanges().gamutC
94
+ if (Array.isArray(xy)) {
95
+ xy = {
96
+ x: xy[0],
97
+ y: xy[1]
98
+ }
99
+ }
100
+
101
+ const v0 = [gamut.blue[0] - gamut.red[0], gamut.blue[1] - gamut.red[1]]
102
+ const v1 = [gamut.green[0] - gamut.red[0], gamut.green[1] - gamut.red[1]]
103
+ const v2 = [xy.x - gamut.red[0], xy.y - gamut.red[1]]
104
+
105
+ const dot00 = (v0[0] * v0[0]) + (v0[1] * v0[1])
106
+ const dot01 = (v0[0] * v1[0]) + (v0[1] * v1[1])
107
+ const dot02 = (v0[0] * v2[0]) + (v0[1] * v2[1])
108
+ const dot11 = (v1[0] * v1[0]) + (v1[1] * v1[1])
109
+ const dot12 = (v1[0] * v2[0]) + (v1[1] * v2[1])
110
+
111
+ const invDenom = 1 / (dot00 * dot11 - dot01 * dot01)
112
+
113
+ const u = (dot11 * dot02 - dot01 * dot12) * invDenom
114
+ const v = (dot00 * dot12 - dot01 * dot02) * invDenom
115
+
116
+ return ((u >= 0) && (v >= 0) && (u + v < 1))
117
+ }
118
+
119
+ static getClosestColor(xy, gamut) {
120
+ function getLineDistance(pointA, pointB) {
121
+ return Math.hypot(pointB.x - pointA.x, pointB.y - pointA.y)
122
+ }
123
+
124
+ function getClosestPoint(xy, pointA, pointB) {
125
+ const xy2a = [xy.x - pointA.x, xy.y - pointA.y]
126
+ const a2b = [pointB.x - pointA.x, pointB.y - pointA.y]
127
+ const a2bSqr = Math.pow(a2b[0], 2) + Math.pow(a2b[1], 2)
128
+ const xy2a_dot_a2b = xy2a[0] * a2b[0] + xy2a[1] * a2b[1]
129
+ const t = xy2a_dot_a2b / a2bSqr
130
+
131
+ return {
132
+ x: pointA.x + a2b[0] * t,
133
+ y: pointA.y + a2b[1] * t
134
+ }
135
+ }
136
+
137
+ const greenBlue = {
138
+ a: {
139
+ x: gamut.green[0],
140
+ y: gamut.green[1]
141
+ },
142
+ b: {
143
+ x: gamut.blue[0],
144
+ y: gamut.blue[1]
145
+ }
146
+ }
147
+
148
+ const greenRed = {
149
+ a: {
150
+ x: gamut.green[0],
151
+ y: gamut.green[1]
152
+ },
153
+ b: {
154
+ x: gamut.red[0],
155
+ y: gamut.red[1]
156
+ }
157
+ }
158
+
159
+ const blueRed = {
160
+ a: {
161
+ x: gamut.red[0],
162
+ y: gamut.red[1]
163
+ },
164
+ b: {
165
+ x: gamut.blue[0],
166
+ y: gamut.blue[1]
167
+ }
168
+ }
169
+
170
+ const closestColorPoints = {
171
+ greenBlue: getClosestPoint(xy, greenBlue.a, greenBlue.b),
172
+ greenRed: getClosestPoint(xy, greenRed.a, greenRed.b),
173
+ blueRed: getClosestPoint(xy, blueRed.a, blueRed.b)
174
+ }
175
+
176
+ const distance = {
177
+ greenBlue: getLineDistance(xy, closestColorPoints.greenBlue),
178
+ greenRed: getLineDistance(xy, closestColorPoints.greenRed),
179
+ blueRed: getLineDistance(xy, closestColorPoints.blueRed)
180
+ }
181
+
182
+ let closestDistance
183
+ let closestColor
184
+ for (const i in distance) {
185
+ if (distance.hasOwnProperty(i)) {
186
+ if (!closestDistance) {
187
+ closestDistance = distance[i]
188
+ closestColor = i
189
+ }
190
+
191
+ if (closestDistance > distance[i]) {
192
+ closestDistance = distance[i]
193
+ closestColor = i
194
+ }
195
+ }
196
+ }
197
+ return closestColorPoints[closestColor]
198
+ }
199
+
200
+ static xyBriToRgb(x, y, bri) {
201
+ function getReversedGammaCorrectedValue(value) {
202
+ return value <= 0.0031308 ? 12.92 * value : (1.0 + 0.055) * Math.pow(value, (1.0 / 2.4)) - 0.055
203
+ }
204
+
205
+ const z = 1.0 - x - y
206
+ const Y = bri / 255
207
+ const X = (Y / y) * x
208
+ const Z = (Y / y) * z
209
+ let r = X * 1.612 - Y * 0.203 - Z * 0.302
210
+ let g = -X * 0.509 + Y * 1.412 + Z * 0.066
211
+ let b = X * 0.026 - Y * 0.072 + Z * 0.962
212
+
213
+ r = getReversedGammaCorrectedValue(r)
214
+ g = getReversedGammaCorrectedValue(g)
215
+ b = getReversedGammaCorrectedValue(b)
216
+
217
+ // Bring all negative components to zero
218
+ r = Math.max(r, 0)
219
+ g = Math.max(g, 0)
220
+ b = Math.max(b, 0)
221
+
222
+ // If one component is greater than 1, weight components by that value
223
+ const max = Math.max(r, g, b)
224
+ if (max > 1) {
225
+ r = r / max
226
+ g = g / max
227
+ b = b / max
228
+ }
229
+
230
+ return {
231
+ red: Math.floor(r * 255),
232
+ geen: Math.floor(g * 255),
233
+ blue: Math.floor(b * 255)
234
+ }
235
+ }
236
+ }
237
+ exports.ColorConverter = ColorConverter
@@ -1,6 +1,6 @@
1
1
  'use strict'
2
2
 
3
- //const hueApi = require('node-hue-api')
3
+ // const hueApi = require('node-hue-api')
4
4
  const hueApiV2 = require('node-hue')
5
5
  const { EventEmitter } = require('events')
6
6
 
@@ -13,30 +13,37 @@ class classHUE extends EventEmitter {
13
13
  this.bridgeid = _bridgeid
14
14
  this.startPushEvents()
15
15
  this.timerWatchDog = undefined
16
+ this.hue = undefined
16
17
  }
17
18
 
18
- getAllLights = async () => {
19
+ // Get all devices and join it with relative rooms, by adding the room name to the device name
20
+ getDevices = async (_rtype) => {
19
21
  try {
20
22
  // V2
21
23
  const hue = hueApiV2.connect({ host: this.HUEBridgeIP, key: this.username })
22
- const allLights = await hue.getLights()
23
- // allLights.forEach(light => {
24
- // console.log(JSON.stringify(light))
25
- // console.log("\n")
26
- // console.log("\n")
27
- // })
28
-
29
- // V2
30
- // const bridgeHUE = await hueApi.v3.api.createLocal(this.HUEBridgeIP).connect(this.username)
31
- // const allLights = await bridgeHUE.lights.getAll()
32
- // allLights.forEach(light => {
33
- // console.log(light.toStringDetailed())
34
- // })
35
-
36
- return { lights: allLights }
24
+ const retArray = []
25
+ const allResources = await hue.getResources()
26
+ const allRooms = await hue.getRooms()
27
+ const newArray = allResources.filter(x => x.type === _rtype)
28
+ // Add room name to the device name
29
+ newArray.forEach(device => {
30
+ // const Room = allRooms.find(room => {
31
+ // return room.children.find(child => child.rid === device.id)
32
+ // })
33
+ const Room = allRooms.find(room => room.children.find(child => child.rid === device.owner.rid))
34
+ const linkedDevName = allResources.find(dev => dev.type === 'device' && dev.services.find(serv => serv.rid === device.id)).metadata.name || ''
35
+ if (_rtype === 'button') {
36
+ const controlID = device.metadata !== undefined ? (device.metadata.control_id || '') : ''
37
+ retArray.push({ name: linkedDevName + (controlID !== '' ? ', button ' + controlID : '') + (Room !== undefined ? ', room ' + Room.metadata.name : ''), id: device.id })
38
+ }
39
+ if (_rtype === 'light') {
40
+ retArray.push({ name: linkedDevName + (Room !== undefined ? ', room ' + Room.metadata.name : ''), id: device.id })
41
+ }
42
+ })
43
+ return { devices: retArray }
37
44
  } catch (error) {
38
- console.log('KNXUltimateHue: classHUE: error ' + error.message)
39
- return ({ lights: error.message })
45
+ console.log('KNXUltimateHue: HueUtils: classHUE: getDevices: error ' + error.message)
46
+ return ({ devices: error.message })
40
47
  }
41
48
  }
42
49
 
@@ -54,11 +61,21 @@ class classHUE extends EventEmitter {
54
61
  }
55
62
  }
56
63
 
64
+ // Get light state
65
+ getLight = async (_LightID) => {
66
+ try {
67
+ const hue = hueApiV2.connect({ host: this.HUEBridgeIP, key: this.username })
68
+ return await hue.getLight(_LightID)
69
+ } catch (error) {
70
+ return ({ error: error.message })
71
+ }
72
+ }
73
+
57
74
  // Check the bridge for disconnections
58
75
  handleTheDog = async () => {
59
76
  this.timerWatchDog = setInterval(async () => {
60
77
  try {
61
- //const hue = hueApiV2.connect({ host: this.HUEBridgeIP, key: this.username })
78
+ // const hue = hueApiV2.connect({ host: this.HUEBridgeIP, key: this.username })
62
79
  if (this.hue !== undefined) {
63
80
  const sRet = await this.hue.getBridges()
64
81
  if (sRet.filter(e => e.bridge_id.toString().toLowerCase() === this.bridgeid.toString().toLowerCase()).length === 0) {
@@ -96,4 +113,3 @@ class classHUE extends EventEmitter {
96
113
  }
97
114
  }
98
115
  module.exports.classHUE = classHUE
99
-
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "node-red-contrib-knx-ultimate",
3
- "version": "2.0.0",
4
- "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.",
3
+ "version": "2.0.2",
4
+ "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.",
5
5
  "dependencies": {
6
6
  "mkdirp": "1.0.4",
7
7
  "ping": "0.4.1",
@@ -14,7 +14,8 @@
14
14
  "xml2js": "0.5.0",
15
15
  "dns-sync": "0.2.1",
16
16
  "node-hue-api": "5.0.0-beta.16",
17
- "node-hue": "1.0.3"
17
+ "node-hue": "1.0.3",
18
+ "color-convert": "2.0.1"
18
19
  },
19
20
  "node-red": {
20
21
  "nodes": {
@@ -28,7 +29,8 @@
28
29
  "knxUltimateLoadControl": "/nodes/knxUltimateLoadControl.js",
29
30
  "knxUltimateViewer": "/nodes/knxUltimateViewer.js",
30
31
  "hueConfig": "/nodes/hue-config.js",
31
- "knxUltimateHueLight": "/nodes/knxUltimateHueLight.js"
32
+ "knxUltimateHueLight": "/nodes/knxUltimateHueLight.js",
33
+ "knxUltimateHueButton": "/nodes/knxUltimateHueButton.js"
32
34
  }
33
35
  },
34
36
  "repository": {
@@ -1,10 +0,0 @@
1
- <script type="text/x-red" data-help-name="knxUltimateHueLight">
2
- <h1>KNX Ultimate - Nodo HUE</h1>
3
-
4
-
5
-
6
- <p>
7
- <a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
8
-
9
- </p>
10
- </script>