node-red-contrib-huemagic 2.8.2 → 4.0.0
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 +229 -0
- package/README.md +806 -729
- package/examples/Hue Bridge.json +189 -35
- package/examples/Hue Brightness.json +124 -14
- package/examples/Hue Buttons.json +88 -0
- package/examples/Hue Group.json +575 -63
- package/examples/Hue Light.json +805 -58
- package/examples/Hue Magic.json +69 -24
- package/examples/Hue Motion.json +110 -42
- package/examples/Hue Rules.json +105 -37
- package/examples/Hue Scene.json +145 -28
- package/examples/Hue Temperature.json +124 -14
- package/huemagic/animations/001-sunny.json +22 -22
- package/huemagic/animations/002-cloudy.json +46 -46
- package/huemagic/animations/003-nightsky.json +20 -20
- package/huemagic/animations/004-sunrise.json +54 -54
- package/huemagic/animations/005-sunset.json +46 -46
- package/huemagic/animations/006-fireplace.json +74 -74
- package/huemagic/animations/007-spring.json +31 -31
- package/huemagic/animations/008-autmn.json +23 -23
- package/huemagic/animations/009-winter.json +23 -23
- package/huemagic/animations/010-dirtyfog.json +23 -23
- package/huemagic/animations/011-lgbt.json +49 -50
- package/huemagic/animations/012-rasta.json +28 -29
- package/huemagic/animations/013-strobo.json +30 -31
- package/huemagic/animations/014-randomrainbow.json +30 -31
- package/huemagic/animations/015-sos.json +158 -159
- package/huemagic/animations/016-milkyway.json +83 -0
- package/huemagic/animations/017-beach.json +40 -0
- package/huemagic/animations/018-forest.json +43 -0
- package/huemagic/animations/019-christmas.json +30 -0
- package/huemagic/animations/020-superhero.json +56 -0
- package/huemagic/animations/021-neoncity.json +52 -0
- package/huemagic/animations/previews/001-sunny.gif +0 -0
- package/huemagic/animations/previews/002-cloudy.gif +0 -0
- package/huemagic/animations/previews/003-nightsky.gif +0 -0
- package/huemagic/animations/previews/004-sunrise.gif +0 -0
- package/huemagic/animations/previews/005-sunset.gif +0 -0
- package/huemagic/animations/previews/006-fireplace.gif +0 -0
- package/huemagic/animations/previews/007-spring.gif +0 -0
- package/huemagic/animations/previews/008-autmn.gif +0 -0
- package/huemagic/animations/previews/009-winter.gif +0 -0
- package/huemagic/animations/previews/010-dirtyfog.gif +0 -0
- package/huemagic/animations/previews/011-lgbt.gif +0 -0
- package/huemagic/animations/previews/012-rasta.gif +0 -0
- package/huemagic/animations/previews/013-strobo.gif +0 -0
- package/huemagic/animations/previews/014-randomrainbow.gif +0 -0
- package/huemagic/animations/previews/015-sos.gif +0 -0
- package/huemagic/animations/previews/016-milkyway.gif +0 -0
- package/huemagic/animations/previews/017-beach.gif +0 -0
- package/huemagic/animations/previews/018-forest.gif +0 -0
- package/huemagic/animations/previews/019-christmas.gif +0 -0
- package/huemagic/animations/previews/020-superhero.gif +0 -0
- package/huemagic/animations/previews/021-neoncity.gif +0 -0
- package/huemagic/hue-bridge-config.html +105 -61
- package/huemagic/hue-bridge-config.js +629 -319
- package/huemagic/hue-bridge.html +41 -21
- package/huemagic/hue-bridge.js +191 -398
- package/huemagic/hue-brightness.html +130 -49
- package/huemagic/hue-brightness.js +131 -35
- package/huemagic/hue-buttons.html +197 -0
- package/huemagic/hue-buttons.js +152 -0
- package/huemagic/hue-group.html +137 -60
- package/huemagic/hue-group.js +394 -367
- package/huemagic/hue-light.html +133 -59
- package/huemagic/hue-light.js +551 -336
- package/huemagic/hue-magic.html +91 -237
- package/huemagic/hue-magic.js +57 -27
- package/huemagic/hue-motion.html +128 -50
- package/huemagic/hue-motion.js +116 -87
- package/huemagic/hue-rules.html +121 -50
- package/huemagic/hue-rules.js +84 -64
- package/huemagic/hue-scene.html +96 -115
- package/huemagic/hue-scene.js +65 -96
- package/huemagic/hue-temperature.html +130 -49
- package/huemagic/hue-temperature.js +136 -32
- package/huemagic/icons/hue-bridge.png +0 -0
- package/huemagic/icons/hue-bridge.svg +3 -0
- package/huemagic/icons/hue-brightness.png +0 -0
- package/huemagic/icons/hue-brightness.svg +11 -0
- package/huemagic/icons/hue-buttons.png +0 -0
- package/huemagic/icons/hue-buttons.svg +4 -0
- package/huemagic/icons/hue-group.png +0 -0
- package/huemagic/icons/hue-group.svg +12 -0
- package/huemagic/icons/hue-light.png +0 -0
- package/huemagic/icons/hue-light.svg +3 -0
- package/huemagic/icons/hue-magic.png +0 -0
- package/huemagic/icons/hue-magic.svg +3 -0
- package/huemagic/icons/hue-motion.png +0 -0
- package/huemagic/icons/hue-motion.svg +9 -0
- package/huemagic/icons/hue-rules.png +0 -0
- package/huemagic/icons/hue-rules.svg +4 -0
- package/huemagic/icons/hue-scene.png +0 -0
- package/huemagic/icons/hue-scene.svg +5 -0
- package/huemagic/icons/hue-temperature.png +0 -0
- package/huemagic/icons/hue-temperature.svg +7 -0
- package/huemagic/locales/de/hue-bridge-config.html +17 -12
- package/huemagic/locales/de/hue-bridge-config.json +7 -5
- package/huemagic/locales/de/hue-bridge.html +64 -145
- package/huemagic/locales/de/hue-bridge.json +6 -17
- package/huemagic/locales/de/hue-brightness.html +52 -38
- package/huemagic/locales/de/hue-brightness.json +7 -2
- package/huemagic/locales/de/hue-buttons.html +58 -0
- package/huemagic/locales/de/hue-buttons.json +28 -0
- package/huemagic/locales/de/hue-group.html +46 -122
- package/huemagic/locales/de/hue-group.json +4 -2
- package/huemagic/locales/de/hue-light.html +68 -116
- package/huemagic/locales/de/hue-light.json +5 -2
- package/huemagic/locales/de/hue-magic.html +65 -57
- package/huemagic/locales/de/hue-magic.json +2 -1
- package/huemagic/locales/de/hue-motion.html +48 -44
- package/huemagic/locales/de/hue-motion.json +6 -3
- package/huemagic/locales/de/hue-rules.html +68 -73
- package/huemagic/locales/de/hue-rules.json +5 -2
- package/huemagic/locales/de/hue-scene.html +23 -32
- package/huemagic/locales/de/hue-scene.json +5 -2
- package/huemagic/locales/de/hue-temperature.html +53 -36
- package/huemagic/locales/de/hue-temperature.json +7 -2
- package/huemagic/locales/en-US/hue-bridge-config.html +17 -12
- package/huemagic/locales/en-US/hue-bridge-config.json +5 -3
- package/huemagic/locales/en-US/hue-bridge.html +64 -145
- package/huemagic/locales/en-US/hue-bridge.json +5 -16
- package/huemagic/locales/en-US/hue-brightness.html +52 -38
- package/huemagic/locales/en-US/hue-brightness.json +10 -3
- package/huemagic/locales/en-US/hue-buttons.html +58 -0
- package/huemagic/locales/en-US/hue-buttons.json +34 -0
- package/huemagic/locales/en-US/hue-group.html +46 -122
- package/huemagic/locales/en-US/hue-group.json +7 -3
- package/huemagic/locales/en-US/hue-light.html +68 -116
- package/huemagic/locales/en-US/hue-light.json +8 -3
- package/huemagic/locales/en-US/hue-magic.html +65 -57
- package/huemagic/locales/en-US/hue-magic.json +3 -1
- package/huemagic/locales/en-US/hue-motion.html +48 -44
- package/huemagic/locales/en-US/hue-motion.json +9 -4
- package/huemagic/locales/en-US/hue-rules.html +68 -73
- package/huemagic/locales/en-US/hue-rules.json +5 -2
- package/huemagic/locales/en-US/hue-scene.html +23 -32
- package/huemagic/locales/en-US/hue-scene.json +5 -2
- package/huemagic/locales/en-US/hue-temperature.html +53 -36
- package/huemagic/locales/en-US/hue-temperature.json +10 -3
- package/huemagic/utils/api.js +290 -0
- package/huemagic/utils/color.js +382 -0
- package/{utils → huemagic/utils}/merge.js +9 -6
- package/huemagic/utils/messages.js +447 -0
- package/package.json +12 -12
- package/examples/Hue Switch.json +0 -40
- package/examples/Hue Tap.json +0 -40
- package/huemagic/assets/anime.js +0 -8
- package/huemagic/hue-switch.html +0 -119
- package/huemagic/hue-switch.js +0 -113
- package/huemagic/hue-tap.html +0 -119
- package/huemagic/hue-tap.js +0 -74
- package/huemagic/icons/hue-button.png +0 -0
- package/huemagic/icons/hue-switch.png +0 -0
- package/huemagic/icons/hue-tap.png +0 -0
- package/huemagic/locales/de/hue-switch.html +0 -50
- package/huemagic/locales/de/hue-switch.json +0 -31
- package/huemagic/locales/de/hue-tap.html +0 -41
- package/huemagic/locales/de/hue-tap.json +0 -23
- package/huemagic/locales/en-US/hue-switch.html +0 -50
- package/huemagic/locales/en-US/hue-switch.json +0 -31
- package/huemagic/locales/en-US/hue-tap.html +0 -41
- package/huemagic/locales/en-US/hue-tap.json +0 -23
- package/utils/messages.js +0 -571
- package/utils/rgb.js +0 -188
package/huemagic/hue-light.js
CHANGED
|
@@ -6,21 +6,18 @@ module.exports = function(RED)
|
|
|
6
6
|
{
|
|
7
7
|
RED.nodes.createNode(this, config);
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
let path = require('path');
|
|
12
|
-
let { HueLightMessage } = require('../utils/messages');
|
|
9
|
+
const scope = this;
|
|
10
|
+
const bridge = RED.nodes.getNode(config.bridge);
|
|
13
11
|
|
|
14
|
-
// SAVE
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
// SAVE FUTURE PATCH
|
|
13
|
+
this.futurePatchState = {};
|
|
14
|
+
|
|
15
|
+
// SAVE LAST COMMAND
|
|
16
|
+
this.lastCommand = null;
|
|
17
17
|
|
|
18
18
|
// HELPER
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
let hexRGB = require('hex-rgb');
|
|
22
|
-
let colornames = require("colornames");
|
|
23
|
-
let getColors = require('get-image-colors');
|
|
19
|
+
const colorUtils = require('./utils/color');
|
|
20
|
+
const merge = require('./utils/merge');
|
|
24
21
|
|
|
25
22
|
//
|
|
26
23
|
// CHECK CONFIG
|
|
@@ -30,365 +27,526 @@ module.exports = function(RED)
|
|
|
30
27
|
return false;
|
|
31
28
|
}
|
|
32
29
|
|
|
30
|
+
//
|
|
31
|
+
// UNIVERSAL MODE?
|
|
32
|
+
if(!config.lightid)
|
|
33
|
+
{
|
|
34
|
+
this.status({fill: "grey", shape: "dot", text: "hue-light.node.universal"});
|
|
35
|
+
}
|
|
36
|
+
|
|
33
37
|
//
|
|
34
38
|
// UPDATE STATE
|
|
35
|
-
if(typeof bridge.disableupdates != 'undefined'||bridge.disableupdates == false)
|
|
39
|
+
if(typeof bridge.disableupdates != 'undefined' || bridge.disableupdates == false)
|
|
36
40
|
{
|
|
37
41
|
this.status({fill: "grey", shape: "dot", text: "hue-light.node.init"});
|
|
38
42
|
}
|
|
39
43
|
|
|
40
44
|
//
|
|
41
|
-
//
|
|
42
|
-
|
|
45
|
+
// SUBSCRIBE TO UPDATES FROM THE BRIDGE
|
|
46
|
+
bridge.subscribe("light", config.lightid, function(info)
|
|
43
47
|
{
|
|
44
|
-
bridge.
|
|
48
|
+
let currentState = bridge.get("light", info.id, { colornames: config.colornamer ? true : false });
|
|
49
|
+
|
|
50
|
+
// RESSOURCE FOUND?
|
|
51
|
+
if(currentState !== false)
|
|
45
52
|
{
|
|
46
|
-
|
|
47
|
-
|
|
53
|
+
// SEND MESSAGE
|
|
54
|
+
if(!config.skipevents && (config.initevents || info.suppressMessage == false))
|
|
55
|
+
{
|
|
56
|
+
// SET LAST COMMAND
|
|
57
|
+
if(scope.lastCommand !== null)
|
|
58
|
+
{
|
|
59
|
+
currentState.command = scope.lastCommand;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// SEND STATE
|
|
63
|
+
scope.send(currentState);
|
|
48
64
|
|
|
49
|
-
|
|
50
|
-
|
|
65
|
+
// RESET LAST COMMAND
|
|
66
|
+
scope.lastCommand = null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// NOT IN UNIVERAL MODE? -> CHANGE UI STATES
|
|
70
|
+
if(config.lightid)
|
|
51
71
|
{
|
|
52
|
-
if(
|
|
72
|
+
if(currentState.payload.reachable === true)
|
|
53
73
|
{
|
|
54
|
-
|
|
55
|
-
if(futureState != null)
|
|
74
|
+
if(currentState.payload.on === true)
|
|
56
75
|
{
|
|
57
|
-
|
|
58
|
-
|
|
76
|
+
// APPLY FUTURE STATE COMMANDS
|
|
77
|
+
if(Object.values(scope.futurePatchState).length > 0)
|
|
78
|
+
{
|
|
79
|
+
scope.applyCommands({}, null, null);
|
|
80
|
+
}
|
|
59
81
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
82
|
+
if(currentState.payload.brightness !== false)
|
|
83
|
+
{
|
|
84
|
+
scope.status({fill: "yellow", shape: "dot", text: RED._("hue-light.node.turned-on-percent",{ percent: currentState.payload.brightness })});
|
|
85
|
+
}
|
|
86
|
+
else
|
|
87
|
+
{
|
|
88
|
+
scope.status({fill: "yellow", shape: "dot", text: "hue-light.node.turned-on"});
|
|
89
|
+
}
|
|
65
90
|
}
|
|
66
|
-
// IS SMART PLUG
|
|
67
91
|
else
|
|
68
92
|
{
|
|
69
|
-
|
|
70
|
-
scope.status({fill: "yellow", shape: "dot", text: "hue-light.node.turned-on"});
|
|
93
|
+
scope.status({fill: "grey", shape: "dot", text: "hue-light.node.turned-off"});
|
|
71
94
|
}
|
|
72
95
|
}
|
|
73
96
|
else
|
|
74
97
|
{
|
|
75
|
-
|
|
98
|
+
var offNotReachableStatus = RED._("hue-light.node.turned-off") + " (" + RED._("hue-light.node.not-reachable") + ")";
|
|
99
|
+
scope.status({fill: "red", shape: "ring", text: offNotReachableStatus});
|
|
76
100
|
}
|
|
77
101
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
var offNotReachableStatus = RED._("hue-light.node.turned-off") + " (" + RED._("hue-light.node.not-reachable") + ")";
|
|
81
|
-
scope.status({fill: "red", shape: "ring", text: offNotReachableStatus});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// SEND MESSAGE
|
|
85
|
-
if(!config.skipevents) { scope.send(hueLight.msg); }
|
|
86
|
-
|
|
87
|
-
// SAVE LAST STATE
|
|
88
|
-
lastState = light;
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
else
|
|
92
|
-
{
|
|
93
|
-
scope.status({fill: "grey", shape: "dot", text: "hue-light.node.universal"});
|
|
94
|
-
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
95
104
|
|
|
105
|
+
//
|
|
106
|
+
// CONTROL LIGHT
|
|
107
|
+
this.on('input', function(msg, send, done) { scope.applyCommands(msg, send, done); });
|
|
96
108
|
|
|
97
109
|
//
|
|
98
|
-
//
|
|
99
|
-
this.
|
|
110
|
+
// APPLY COMMANDS
|
|
111
|
+
this.applyCommands = async function(msg, send = null, done = null)
|
|
100
112
|
{
|
|
101
|
-
//
|
|
113
|
+
// REDEFINE SEND AND DONE IF NOT AVAILABLE
|
|
102
114
|
send = send || function() { scope.send.apply(scope,arguments); }
|
|
103
|
-
scope.
|
|
104
|
-
});
|
|
115
|
+
done = done || function() { scope.done.apply(scope,arguments); }
|
|
105
116
|
|
|
117
|
+
// SAVE LAST COMMAND
|
|
118
|
+
scope.lastCommand = msg;
|
|
106
119
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
120
|
+
// CREATE PATCH
|
|
121
|
+
let patchObject = {};
|
|
122
|
+
|
|
123
|
+
// DEFINE SENSOR ID & CURRENT STATE
|
|
124
|
+
const tempLightID = (msg.topic != null) ? msg.topic : config.lightid;
|
|
125
|
+
let currentState = bridge.get("light", tempLightID, { colornames: config.colornamer ? true : false });
|
|
112
126
|
|
|
113
127
|
// CHECK IF LIGHT ID IS SET
|
|
114
|
-
if(tempLightID
|
|
128
|
+
if(!tempLightID)
|
|
115
129
|
{
|
|
116
130
|
scope.error(RED._("hue-light.node.error-no-id"));
|
|
117
131
|
return false;
|
|
118
132
|
}
|
|
119
133
|
|
|
120
134
|
// GET CURRENT STATE
|
|
121
|
-
if(typeof msg.payload != 'undefined' && typeof msg.payload.status != 'undefined')
|
|
135
|
+
if( (typeof msg.payload != 'undefined' && typeof msg.payload.status != 'undefined') || (typeof msg.__user_inject_props__ != 'undefined' && msg.__user_inject_props__ == "status") )
|
|
122
136
|
{
|
|
123
|
-
|
|
124
|
-
.
|
|
125
|
-
|
|
126
|
-
|
|
137
|
+
// SET LAST COMMAND
|
|
138
|
+
if(scope.lastCommand !== null)
|
|
139
|
+
{
|
|
140
|
+
currentState.command = scope.lastCommand;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// SEND STATE
|
|
144
|
+
scope.send(currentState);
|
|
127
145
|
|
|
146
|
+
// RESET LAST COMMAND
|
|
147
|
+
scope.lastCommand = null;
|
|
148
|
+
|
|
149
|
+
if(done) { done(); }
|
|
128
150
|
return true;
|
|
129
151
|
}
|
|
130
152
|
|
|
153
|
+
// GET FUTURE STATE
|
|
154
|
+
if(Object.values(scope.futurePatchState).length > 0)
|
|
155
|
+
{
|
|
156
|
+
patchObject = Object.assign({}, scope.futurePatchState);
|
|
157
|
+
scope.futurePatchState = {};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// COLORLOOP EFFECT
|
|
161
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.colorloop != 'undefined' && msg.payload.colorloop > 0)
|
|
162
|
+
{
|
|
163
|
+
patchObject = {
|
|
164
|
+
"on": true,
|
|
165
|
+
"effect": "colorloop",
|
|
166
|
+
"bri": msg.payload.brightness ? Math.round((254/100)*msg.payload.brightness) : currentState.brightnessLevel
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
bridge.patch("light", currentState.info.idV1 + "/state", patchObject, 1)
|
|
170
|
+
.then(function(status) {
|
|
171
|
+
// RESET COLORLOOP ANIMATION AFTER X SECONDS
|
|
172
|
+
setTimeout(function()
|
|
173
|
+
{
|
|
174
|
+
bridge.patch("light", currentState.info.idV1 + "/state", { "effect": "none" }, 1);
|
|
175
|
+
if(done) { done(); }
|
|
176
|
+
}, parseInt(msg.payload.colorloop) * 1000);
|
|
177
|
+
})
|
|
178
|
+
.catch(function(errors) {
|
|
179
|
+
scope.error(errors);
|
|
180
|
+
scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
|
|
131
186
|
// ALERT EFFECT
|
|
132
187
|
if(typeof msg.payload != 'undefined' && typeof msg.payload.alert != 'undefined' && msg.payload.alert > 0)
|
|
133
188
|
{
|
|
134
|
-
|
|
135
|
-
.
|
|
136
|
-
scope.context().set('lightPreviousState', [light.on ? true : false, light.brightness, light.xy ? light.xy : false]);
|
|
189
|
+
// SAVE PREVIOUS STATE
|
|
190
|
+
scope.context().set('lightPreviousState', currentState);
|
|
137
191
|
|
|
138
|
-
|
|
139
|
-
|
|
192
|
+
// TURN ON LIGHT
|
|
193
|
+
if(currentState.payload.on === false)
|
|
194
|
+
{
|
|
195
|
+
patchObject["on"] = { on: true };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// SET BRIGHTNESS
|
|
199
|
+
if(!msg.payload.brightness && currentState.payload.brightness != 100)
|
|
200
|
+
{
|
|
201
|
+
patchObject["dimming"] = { brightness: 100 };
|
|
202
|
+
}
|
|
203
|
+
else if(msg.payload.brightness)
|
|
204
|
+
{
|
|
205
|
+
patchObject["dimming"] = { brightness: parseInt(msg.payload.brightness) };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// SET TRANSITION
|
|
209
|
+
patchObject["dynamics"] = { duration: 0 };
|
|
210
|
+
|
|
211
|
+
// CAN CHANGE COLOR?
|
|
212
|
+
if(currentState.payload.xyColor)
|
|
213
|
+
{
|
|
214
|
+
let XYAlertColor = {};
|
|
215
|
+
|
|
216
|
+
if(typeof msg.payload.rgb != 'undefined')
|
|
140
217
|
{
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
218
|
+
XYAlertColor = colorUtils.rgbToXy(msg.payload.rgb[0], msg.payload.rgb[1], msg.payload.rgb[2], currentState.info.model.colorGamut);
|
|
219
|
+
}
|
|
220
|
+
else if(typeof msg.payload.hex != 'undefined')
|
|
221
|
+
{
|
|
222
|
+
let rgbFromHex = colorUtils.hexRgb((msg.payload.hex).toString());
|
|
223
|
+
XYAlertColor = colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut);
|
|
224
|
+
}
|
|
225
|
+
else if(typeof msg.payload.color != 'undefined')
|
|
226
|
+
{
|
|
227
|
+
if(new RegExp("random|any|whatever").test(msg.payload.color))
|
|
146
228
|
{
|
|
147
|
-
|
|
148
|
-
|
|
229
|
+
const randomColor = colorUtils.randomHexColor();
|
|
230
|
+
let rgbFromHex = colorUtils.hexRgb(rgbFromHex);
|
|
231
|
+
XYAlertColor = colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut);
|
|
149
232
|
}
|
|
150
|
-
else
|
|
233
|
+
else
|
|
151
234
|
{
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
var randomColor = '#'+(Math.random()*0xFFFFFF<<0).toString(16);
|
|
155
|
-
var rgbResult = hexRGB(randomColor);
|
|
156
|
-
light.xy = rgb.convertRGBtoXY([rgbResult.red, rgbResult.green, rgbResult.blue], light.model.id);
|
|
157
|
-
}
|
|
158
|
-
else
|
|
235
|
+
var colorHex = colorUtils.colornames(msg.payload.color);
|
|
236
|
+
if(colorHex)
|
|
159
237
|
{
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
{
|
|
163
|
-
var rgbResult = hexRGB(colorHex);
|
|
164
|
-
light.xy = rgb.convertRGBtoXY([rgbResult.red, rgbResult.green, rgbResult.blue], light.model.id);
|
|
165
|
-
}
|
|
238
|
+
let rgbFromHex = colorUtils.hexRgb(colorHex);
|
|
239
|
+
XYAlertColor = colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut);
|
|
166
240
|
}
|
|
167
241
|
}
|
|
168
|
-
else
|
|
169
|
-
{
|
|
170
|
-
light.xy = rgb.convertRGBtoXY([255,0,0], light.model.id);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// ACTIVATE
|
|
175
|
-
light.on = true;
|
|
176
|
-
light.brightness = 254;
|
|
177
|
-
light.transitionTime = 0;
|
|
178
|
-
return bridge.client.lights.save(light);
|
|
179
|
-
})
|
|
180
|
-
.then(light => {
|
|
181
|
-
if(!config.lightid) { scope.sendLightStatus(light, send, done); }
|
|
182
|
-
return light;
|
|
183
|
-
})
|
|
184
|
-
.then(light => {
|
|
185
|
-
// ACTIVATE ALERT
|
|
186
|
-
if(light != false)
|
|
187
|
-
{
|
|
188
|
-
light.alert = 'lselect';
|
|
189
|
-
return bridge.client.lights.save(light);
|
|
190
242
|
}
|
|
191
243
|
else
|
|
192
244
|
{
|
|
193
|
-
|
|
245
|
+
XYAlertColor = colorUtils.rgbToXy(255, 0, 0, currentState.info.model.colorGamut);
|
|
194
246
|
}
|
|
247
|
+
|
|
248
|
+
patchObject["color"] = {
|
|
249
|
+
xy: XYAlertColor
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// CHANGE NODE UI STATE
|
|
254
|
+
if(config.lightid)
|
|
255
|
+
{
|
|
256
|
+
scope.status({fill: "grey", shape: "ring", text: "hue-light.node.command"});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// 1. TURN ON THE LIGHT BULB
|
|
260
|
+
bridge.patch("light", tempLightID, patchObject)
|
|
261
|
+
.then(function(status) {
|
|
262
|
+
// 2. APPLY ALERT EFFECT
|
|
263
|
+
const alertEffect = { alert: { action: "breathe" }};
|
|
264
|
+
return bridge.patch("light", tempLightID, alertEffect);
|
|
195
265
|
})
|
|
196
|
-
.then(
|
|
197
|
-
//
|
|
198
|
-
|
|
266
|
+
.then(function(status) {
|
|
267
|
+
// 3. RESET PREVIOUS STATE (AFTER X SECONDS)
|
|
268
|
+
setTimeout(function()
|
|
199
269
|
{
|
|
200
|
-
|
|
201
|
-
var
|
|
270
|
+
const tempPreviousState = scope.context().get('lightPreviousState');
|
|
271
|
+
var tempPreviousStatePatch = {};
|
|
202
272
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
273
|
+
tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
|
|
274
|
+
if(tempPreviousState.payload.xyColor)
|
|
275
|
+
{
|
|
276
|
+
tempPreviousStatePatch.color = { xy: tempPreviousState.payload.xyColor };
|
|
277
|
+
}
|
|
278
|
+
else if(tempPreviousState.payload.colorTemp)
|
|
279
|
+
{
|
|
280
|
+
tempPreviousStatePatch.color_temperature = { mirek: tempPreviousState.payload.colorTemp };
|
|
281
|
+
}
|
|
208
282
|
|
|
209
|
-
|
|
283
|
+
bridge.patch("light", tempLightID, tempPreviousStatePatch).
|
|
284
|
+
then(function(status)
|
|
285
|
+
{
|
|
286
|
+
return bridge.patch("light", tempLightID, { on: { on: false } })
|
|
287
|
+
.then(function() { if(done) { done(); }});
|
|
288
|
+
})
|
|
289
|
+
.then(function(status) {
|
|
290
|
+
if(tempPreviousState.payload.on === true)
|
|
210
291
|
{
|
|
211
|
-
light
|
|
292
|
+
bridge.patch("light", tempLightID, { on: { on: true } })
|
|
293
|
+
.then(function() { if(done) { done(); }});
|
|
212
294
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
}, alertSeconds * 1000);
|
|
216
|
-
}
|
|
295
|
+
});
|
|
296
|
+
}, parseInt(msg.payload.alert) * 1000);
|
|
217
297
|
})
|
|
218
|
-
.catch(
|
|
219
|
-
scope.error(
|
|
298
|
+
.catch(function(errors) {
|
|
299
|
+
scope.error(errors);
|
|
220
300
|
scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
|
|
221
|
-
if(done) { done(error); }
|
|
222
301
|
});
|
|
223
302
|
}
|
|
224
303
|
// ANIMATION STARTED?
|
|
225
304
|
else if(typeof msg.animation != 'undefined' && msg.animation.status == true && msg.animation.restore == true)
|
|
226
305
|
{
|
|
227
|
-
|
|
228
|
-
.
|
|
229
|
-
scope.context().set('lightPreviousState', [(light.on) ? true : false, light.brightness, light.xy ? light.xy : false]);
|
|
230
|
-
})
|
|
231
|
-
.catch(error => {
|
|
232
|
-
scope.error(error, msg);
|
|
233
|
-
scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
|
|
234
|
-
if(done) { done(error); }
|
|
235
|
-
});
|
|
306
|
+
// SAVE PREVIOUS STATE
|
|
307
|
+
scope.context().set('lightPreviousState', currentState);
|
|
236
308
|
}
|
|
237
309
|
// ANIMATION STOPPED AND RESTORE ACTIVE?
|
|
238
310
|
else if(typeof msg.animation != 'undefined' && msg.animation.status == false && msg.animation.restore == true)
|
|
239
311
|
{
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
var lightPreviousState = scope.context().get('lightPreviousState');
|
|
243
|
-
light.on = lightPreviousState[0];
|
|
244
|
-
light.alert = 'none';
|
|
245
|
-
light.brightness = lightPreviousState[1];
|
|
246
|
-
light.transitionTime = 2;
|
|
312
|
+
const tempPreviousState = scope.context().get('lightPreviousState');
|
|
313
|
+
var tempPreviousStatePatch = {};
|
|
247
314
|
|
|
248
|
-
|
|
315
|
+
tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
|
|
316
|
+
if(tempPreviousState.payload.xyColor)
|
|
317
|
+
{
|
|
318
|
+
tempPreviousStatePatch.color = { xy: tempPreviousState.payload.xyColor };
|
|
319
|
+
}
|
|
320
|
+
else if(tempPreviousState.payload.colorTemp)
|
|
321
|
+
{
|
|
322
|
+
tempPreviousStatePatch.color_temperature = { mirek: tempPreviousState.payload.colorTemp };
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
bridge.patch("light", tempLightID, tempPreviousStatePatch).
|
|
326
|
+
then(function(status)
|
|
327
|
+
{
|
|
328
|
+
if(tempPreviousState.payload.on === false)
|
|
249
329
|
{
|
|
250
|
-
light
|
|
330
|
+
bridge.patch("light", tempLightID, { on: { on: false } })
|
|
331
|
+
.then(function() { if(done) { done(); }});
|
|
332
|
+
}
|
|
333
|
+
else
|
|
334
|
+
{
|
|
335
|
+
bridge.patch("light", tempLightID, { on: { on: false } })
|
|
336
|
+
.then(function(status) {
|
|
337
|
+
if(done) { done(); }
|
|
338
|
+
return bridge.patch("light", tempLightID, { on: { on: true } })
|
|
339
|
+
});
|
|
251
340
|
}
|
|
252
|
-
|
|
253
|
-
bridge.client.lights.save(light);
|
|
254
|
-
})
|
|
255
|
-
.catch(error => {
|
|
256
|
-
scope.error(error, msg);
|
|
257
|
-
scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
|
|
258
|
-
if(done) { done(error); }
|
|
259
341
|
});
|
|
260
342
|
}
|
|
261
|
-
// EXTENDED
|
|
343
|
+
// EXTENDED COMMANDS
|
|
262
344
|
else
|
|
263
345
|
{
|
|
264
|
-
|
|
265
|
-
.
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
// SET LIGHT STATE SIMPLE MODE
|
|
270
|
-
if(msg.payload === true||msg.payload === false)
|
|
271
|
-
{
|
|
272
|
-
var command = msg.payload;
|
|
273
|
-
msg.payload = {
|
|
274
|
-
on: command
|
|
275
|
-
};
|
|
276
|
-
}
|
|
346
|
+
// SET LIGHT STATE SIMPLE MODE
|
|
347
|
+
if(msg.payload === true||msg.payload === false)
|
|
348
|
+
{
|
|
349
|
+
if(msg.payload !== currentState.payload.on) { patchObject["on"] = { on: msg.payload }; }
|
|
350
|
+
}
|
|
277
351
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
352
|
+
// SET LIGHT STATE
|
|
353
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.on != 'undefined' && (msg.payload.on === true || msg.payload.on === false))
|
|
354
|
+
{
|
|
355
|
+
if(msg.payload.on !== currentState.payload.on) { patchObject["on"] = { on: msg.payload.on }; }
|
|
356
|
+
}
|
|
283
357
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
358
|
+
// TOGGLE ON / OFF
|
|
359
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.toggle != 'undefined')
|
|
360
|
+
{
|
|
361
|
+
patchObject["on"] = { on: !currentState.payload.on };
|
|
362
|
+
}
|
|
287
363
|
|
|
288
|
-
|
|
289
|
-
|
|
364
|
+
// SET BRIGHTNESS
|
|
365
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.brightness != 'undefined')
|
|
366
|
+
{
|
|
367
|
+
// AUTO BRIGHTNESS BASED ON DAY TIME
|
|
368
|
+
if(new RegExp("auto|automatic").test(msg.payload.brightness))
|
|
290
369
|
{
|
|
291
|
-
|
|
292
|
-
|
|
370
|
+
let ct = colorUtils.colorTemperature();
|
|
371
|
+
let autoBrightness = ((300-ct)/2)+100;
|
|
372
|
+
autoBrightness = (autoBrightness > 100) ? 100 : autoBrightness;
|
|
373
|
+
autoBrightness = (autoBrightness < 20) ? 20 : autoBrightness;
|
|
293
374
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
{
|
|
297
|
-
light.on = light.on ? false : true;
|
|
375
|
+
// SET CALCULATED BRIGHTNESS
|
|
376
|
+
patchObject["dimming"] = { brightness: autoBrightness };
|
|
298
377
|
}
|
|
299
|
-
|
|
300
|
-
// SET BRIGHTNESS
|
|
301
|
-
if(typeof msg.payload != 'undefined' && typeof msg.payload.brightness != 'undefined')
|
|
378
|
+
else
|
|
302
379
|
{
|
|
303
|
-
if(msg.payload.brightness > 100 ||
|
|
380
|
+
if(msg.payload.brightness > 100 || msg.payload.brightness < 0)
|
|
304
381
|
{
|
|
305
382
|
scope.error("Invalid brightness setting. Only 0 - 100 percent allowed");
|
|
306
383
|
return false;
|
|
307
384
|
}
|
|
308
385
|
else if(msg.payload.brightness == 0)
|
|
309
386
|
{
|
|
310
|
-
|
|
387
|
+
if(currentState.payload.on !== false) { patchObject["on"] = { on: false }; }
|
|
311
388
|
}
|
|
312
389
|
else
|
|
313
390
|
{
|
|
314
|
-
|
|
315
|
-
light.brightness = Math.round((254/100)*parseInt(msg.payload.brightness));
|
|
391
|
+
patchObject["dimming"] = { brightness: msg.payload.brightness };
|
|
316
392
|
}
|
|
317
393
|
}
|
|
318
|
-
|
|
394
|
+
}
|
|
395
|
+
else if(typeof msg.payload != 'undefined' && typeof msg.payload.brightnessLevel != 'undefined')
|
|
396
|
+
{
|
|
397
|
+
if(msg.payload.brightnessLevel > 254 || msg.payload.brightnessLevel < 0)
|
|
319
398
|
{
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
scope.error("Invalid brightness setting. Only 0 - 254 allowed");
|
|
323
|
-
return false;
|
|
324
|
-
}
|
|
325
|
-
else if(msg.payload.brightness == 0)
|
|
326
|
-
{
|
|
327
|
-
light.on = false;
|
|
328
|
-
}
|
|
329
|
-
else
|
|
330
|
-
{
|
|
331
|
-
light.on = true;
|
|
332
|
-
light.brightness = parseInt(msg.payload.brightnessLevel);
|
|
333
|
-
}
|
|
399
|
+
scope.error("Invalid brightness setting. Only 0 - 254 allowed");
|
|
400
|
+
return false;
|
|
334
401
|
}
|
|
335
|
-
else if(
|
|
402
|
+
else if(msg.payload.brightness == 0)
|
|
336
403
|
{
|
|
337
|
-
if
|
|
338
|
-
{
|
|
339
|
-
light.on = true;
|
|
340
|
-
}
|
|
341
|
-
light.incrementBrightness = Math.round((254/100)*parseInt(msg.payload.incrementBrightness));
|
|
404
|
+
if(currentState.payload.on !== false) { patchObject["on"] = { on: false }; }
|
|
342
405
|
}
|
|
343
|
-
else
|
|
406
|
+
else
|
|
344
407
|
{
|
|
345
|
-
|
|
408
|
+
patchObject["dimming"] = { brightness: Math.round((100/254)*msg.payload.brightnessLevel) };
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
else if(typeof msg.payload != 'undefined' && typeof msg.payload.incrementBrightness != 'undefined')
|
|
412
|
+
{
|
|
413
|
+
let incrementBy = (isNaN(msg.payload.incrementBrightness)) ? 10 : msg.payload.incrementBrightness;
|
|
414
|
+
let targetBrightness = Math.round(currentState.payload.brightness + incrementBy);
|
|
415
|
+
targetBrightness = (targetBrightness > 100) ? 100 : targetBrightness;
|
|
416
|
+
|
|
417
|
+
patchObject["dimming"] = { brightness: targetBrightness };
|
|
418
|
+
}
|
|
419
|
+
else if(typeof msg.payload != 'undefined' && typeof msg.payload.decrementBrightness != 'undefined')
|
|
420
|
+
{
|
|
421
|
+
let decrementBy = (isNaN(msg.payload.decrementBrightness)) ? 10 : msg.payload.decrementBrightness;
|
|
422
|
+
let targetBrightness = Math.round(currentState.payload.brightness - decrementBy);
|
|
423
|
+
targetBrightness = (targetBrightness < 0) ? 0 : targetBrightness;
|
|
424
|
+
|
|
425
|
+
if(targetBrightness < 1)
|
|
426
|
+
{
|
|
427
|
+
if(currentState.payload.on !== false) { patchObject["on"] = { on: false }; }
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
patchObject["dimming"] = { brightness: targetBrightness };
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// SET HUMAN READABLE COLOR OR RANDOM
|
|
434
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.color != 'undefined' && typeof currentState.payload.xyColor != 'undefined')
|
|
435
|
+
{
|
|
436
|
+
let XYAlertColor = {};
|
|
437
|
+
|
|
438
|
+
if(new RegExp("random|any|whatever").test(msg.payload.color))
|
|
439
|
+
{
|
|
440
|
+
const randomColor = colorUtils.randomHexColor();
|
|
441
|
+
let rgbFromHex = colorUtils.hexRgb(randomColor);
|
|
442
|
+
XYAlertColor = colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut);
|
|
443
|
+
}
|
|
444
|
+
else
|
|
445
|
+
{
|
|
446
|
+
var colorHex = colorUtils.colornames(msg.payload.color);
|
|
447
|
+
if(colorHex)
|
|
346
448
|
{
|
|
347
|
-
|
|
449
|
+
let rgbFromHex = colorUtils.hexRgb(colorHex);
|
|
450
|
+
XYAlertColor = colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut);
|
|
348
451
|
}
|
|
349
|
-
light.incrementBrightness = Math.round((254/100)*parseInt(msg.payload.decrementBrightness))*-1;
|
|
350
452
|
}
|
|
351
453
|
|
|
352
|
-
|
|
353
|
-
|
|
454
|
+
patchObject["color"] = {
|
|
455
|
+
xy: XYAlertColor
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// SET HEX COLOR
|
|
460
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.hex != 'undefined' && typeof currentState.payload.xyColor != 'undefined')
|
|
461
|
+
{
|
|
462
|
+
let rgbFromHex = colorUtils.hexRgb((msg.payload.hex).toString());
|
|
463
|
+
patchObject["color"] = {
|
|
464
|
+
xy: colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut)
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// SET RGB COLOR
|
|
469
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.rgb != 'undefined' && typeof currentState.payload.xyColor != 'undefined' && msg.payload.rgb.length === 3)
|
|
470
|
+
{
|
|
471
|
+
patchObject["color"] = {
|
|
472
|
+
xy: colorUtils.rgbToXy(msg.payload.rgb[0], msg.payload.rgb[1], msg.payload.rgb[2], currentState.info.model.colorGamut)
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// SET XY COLOR
|
|
477
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.xyColor != 'undefined' && typeof currentState.payload.xyColor != 'undefined')
|
|
478
|
+
{
|
|
479
|
+
patchObject["color"] = {
|
|
480
|
+
xy: msg.payload.xyColor
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// MIX CURRENT COLOR WITH NEW COLOR
|
|
485
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.mixColor != 'undefined' && typeof currentState.payload.xyColor != 'undefined')
|
|
486
|
+
{
|
|
487
|
+
let RGBColor = [];
|
|
488
|
+
|
|
489
|
+
if(typeof msg.payload.mixColor.color != 'undefined')
|
|
354
490
|
{
|
|
355
|
-
if(new RegExp("random|any|whatever").test(msg.payload.color))
|
|
491
|
+
if(new RegExp("random|any|whatever").test(msg.payload.mixColor.color))
|
|
356
492
|
{
|
|
357
|
-
|
|
358
|
-
var rgbResult = hexRGB(randomColor);
|
|
359
|
-
light.xy = rgb.convertRGBtoXY([rgbResult.red, rgbResult.green, rgbResult.blue], light.model.id);
|
|
493
|
+
RGBColor = colorUtils.hexRgb(colorUtils.randomHexColor());
|
|
360
494
|
}
|
|
361
495
|
else
|
|
362
496
|
{
|
|
363
|
-
var colorHex = colornames(msg.payload.color);
|
|
497
|
+
var colorHex = colorUtils.colornames(msg.payload.mixColor.color);
|
|
364
498
|
if(colorHex)
|
|
365
499
|
{
|
|
366
|
-
|
|
367
|
-
light.xy = rgb.convertRGBtoXY([rgbResult.red, rgbResult.green, rgbResult.blue], light.model.id);
|
|
500
|
+
RGBColor = colorUtils.hexRgb(colorHex);
|
|
368
501
|
}
|
|
369
502
|
}
|
|
370
503
|
}
|
|
504
|
+
else if(typeof msg.payload.mixColor.rgb != 'undefined')
|
|
505
|
+
{
|
|
506
|
+
RGBColor = msg.payload.mixColor.rgb;
|
|
507
|
+
}
|
|
508
|
+
else if(typeof msg.payload.mixColor.hex != 'undefined')
|
|
509
|
+
{
|
|
510
|
+
RGBColor = colorUtils.hexRgb((msg.payload.mixColor.hex).toString());
|
|
511
|
+
}
|
|
512
|
+
else if(typeof msg.payload.mixColor.xyColor != 'undefined')
|
|
513
|
+
{
|
|
514
|
+
RGBColor = colorUtils.xyBriToRgb(msg.payload.mixColor.xyColor.x, msg.payload.mixColor.xyColor.y, 100);
|
|
515
|
+
}
|
|
371
516
|
|
|
372
|
-
//
|
|
373
|
-
|
|
517
|
+
// GET MIXING AMOUNT
|
|
518
|
+
let mixingAmount = 0.5;
|
|
519
|
+
if(typeof msg.payload.mixColor.amount != 'undefined' && msg.payload.mixColor.amount > 0 && msg.payload.mixColor.amount <= 100)
|
|
374
520
|
{
|
|
375
|
-
|
|
521
|
+
mixingAmount = msg.payload.mixColor.amount/100;
|
|
376
522
|
}
|
|
377
523
|
|
|
378
|
-
//
|
|
379
|
-
if(
|
|
524
|
+
// HAS CURRENT COLOR SETTING?
|
|
525
|
+
if(currentState.payload.rgb !== false)
|
|
526
|
+
{
|
|
527
|
+
let mixedRGBColor = colorUtils.mixColors(currentState.payload.rgb, RGBColor, mixingAmount);
|
|
528
|
+
patchObject["color"] = {
|
|
529
|
+
xy: colorUtils.rgbToXy(mixedRGBColor[0], mixedRGBColor[1], mixedRGBColor[2], currentState.info.model.colorGamut)
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
else
|
|
380
533
|
{
|
|
381
|
-
|
|
382
|
-
|
|
534
|
+
patchObject["color"] = {
|
|
535
|
+
xy: colorUtils.rgbToXy(RGBColor[0], RGBColor[1], RGBColor[2], currentState.info.model.colorGamut)
|
|
536
|
+
};
|
|
383
537
|
}
|
|
538
|
+
}
|
|
384
539
|
|
|
385
|
-
|
|
386
|
-
|
|
540
|
+
// SET COLOR TEMPERATURE
|
|
541
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.colorTemp != 'undefined' && typeof currentState.payload.colorTemp != 'undefined')
|
|
542
|
+
{
|
|
543
|
+
// DETERMINE IF AUTOMATIC, WARM, COLD, INT
|
|
544
|
+
if(!isNaN(msg.payload.colorTemp))
|
|
387
545
|
{
|
|
388
546
|
let colorTemp = parseInt(msg.payload.colorTemp);
|
|
389
547
|
if(colorTemp >= 153 && colorTemp <= 500)
|
|
390
548
|
{
|
|
391
|
-
|
|
549
|
+
patchObject["color_temperature"] = { mirek: colorTemp };
|
|
392
550
|
}
|
|
393
551
|
else
|
|
394
552
|
{
|
|
@@ -396,131 +554,188 @@ module.exports = function(RED)
|
|
|
396
554
|
return false;
|
|
397
555
|
}
|
|
398
556
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
557
|
+
else if(msg.payload.colorTemp == "cold")
|
|
558
|
+
{
|
|
559
|
+
patchObject["color_temperature"] = { mirek: 153 };
|
|
560
|
+
}
|
|
561
|
+
else if(msg.payload.colorTemp == "normal")
|
|
562
|
+
{
|
|
563
|
+
patchObject["color_temperature"] = { mirek: 240 };
|
|
564
|
+
}
|
|
565
|
+
else if(msg.payload.colorTemp == "warm")
|
|
566
|
+
{
|
|
567
|
+
patchObject["color_temperature"] = { mirek: 400 };
|
|
568
|
+
}
|
|
569
|
+
else if(msg.payload.colorTemp == "hot")
|
|
570
|
+
{
|
|
571
|
+
patchObject["color_temperature"] = { mirek: 500 };
|
|
572
|
+
}
|
|
573
|
+
else
|
|
574
|
+
{
|
|
575
|
+
// SET TEMPERATURE
|
|
576
|
+
patchObject["color_temperature"] = { mirek: colorUtils.colorTemperature() };
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
else if(typeof msg.payload != 'undefined' && typeof msg.payload.incrementColorTemp != 'undefined' && typeof currentState.payload.colorTemp != 'undefined')
|
|
580
|
+
{
|
|
581
|
+
let incrementBy = (isNaN(msg.payload.incrementColorTemp)) ? 50 : msg.payload.incrementColorTemp;
|
|
582
|
+
let targetColorTemperature = currentState.payload.colorTemp + parseInt(incrementBy);
|
|
583
|
+
targetColorTemperature = (targetColorTemperature > 500) ? 500 : targetColorTemperature;
|
|
584
|
+
targetColorTemperature = (targetColorTemperature < 153) ? 153 : targetColorTemperature;
|
|
403
585
|
|
|
404
|
-
// SET
|
|
405
|
-
|
|
586
|
+
// SET TEMPERATURE
|
|
587
|
+
patchObject["color_temperature"] = { mirek: targetColorTemperature };
|
|
588
|
+
}
|
|
589
|
+
else if(typeof msg.payload != 'undefined' && typeof msg.payload.decrementColorTemp != 'undefined' && typeof currentState.payload.colorTemp != 'undefined')
|
|
590
|
+
{
|
|
591
|
+
let decrementBy = (isNaN(msg.payload.decrementColorTemp)) ? 50 : msg.payload.decrementColorTemp;
|
|
592
|
+
let targetColorTemperature = currentState.payload.colorTemp - parseInt(decrementBy);
|
|
593
|
+
targetColorTemperature = (targetColorTemperature > 500) ? 500 : targetColorTemperature;
|
|
594
|
+
targetColorTemperature = (targetColorTemperature < 153) ? 153 : targetColorTemperature;
|
|
595
|
+
|
|
596
|
+
// SET TEMPERATURE
|
|
597
|
+
patchObject["color_temperature"] = { mirek: targetColorTemperature };
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// SET TRANSITION TIME
|
|
601
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.transitionTime != 'undefined')
|
|
602
|
+
{
|
|
603
|
+
let targetTransitionTime = parseFloat(msg.payload.transitionTime)*1000;
|
|
604
|
+
targetTransitionTime = (targetTransitionTime > 6000000) ? 6000000 : targetTransitionTime;
|
|
605
|
+
targetTransitionTime = (targetTransitionTime < 0) ? 0 : targetTransitionTime;
|
|
606
|
+
|
|
607
|
+
patchObject["dynamics"] = { duration: targetTransitionTime };
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
// SET DOMINANT COLORS FROM IMAGE
|
|
611
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.image != 'undefined' && typeof currentState.payload.xyColor != 'undefined')
|
|
612
|
+
{
|
|
613
|
+
var colors = await colorUtils.getColors(msg.payload.image);
|
|
614
|
+
if(colors.length > 0)
|
|
406
615
|
{
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
else
|
|
413
|
-
{
|
|
414
|
-
light.saturation = Math.round((254/100)*parseInt(msg.payload.saturation));
|
|
415
|
-
}
|
|
616
|
+
var colorsHEX = colors.map(color => color.hex());
|
|
617
|
+
let rgbFromHex = colorUtils.hexRgb(colorsHEX[0]);
|
|
618
|
+
patchObject["color"] = {
|
|
619
|
+
xy: colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut)
|
|
620
|
+
};
|
|
416
621
|
}
|
|
622
|
+
}
|
|
417
623
|
|
|
418
|
-
|
|
419
|
-
|
|
624
|
+
// SET SATURATION
|
|
625
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.saturation != 'undefined' && typeof currentState.payload.xyColor != 'undefined')
|
|
626
|
+
{
|
|
627
|
+
if(msg.payload.saturation > 100 || msg.payload.saturation < 0)
|
|
420
628
|
{
|
|
421
|
-
|
|
629
|
+
scope.error("Invalid saturation setting. Only 0 - 100 allowed");
|
|
630
|
+
return false;
|
|
422
631
|
}
|
|
632
|
+
else
|
|
633
|
+
{
|
|
634
|
+
let currentColor = patchObject["color"] ? colorUtils.xyBriToRgb(patchObject["color"].xy.x, patchObject["color"].xy.y, 100) : currentState.payload.rgb;
|
|
635
|
+
let currentColorInHSL = colorUtils.rgbToHsl(currentColor[0], currentColor[1], currentColor[2]);
|
|
636
|
+
let saturationFactor = (msg.payload.saturation/100);
|
|
423
637
|
|
|
424
|
-
|
|
425
|
-
|
|
638
|
+
// CHANGE SATURATION
|
|
639
|
+
currentColorInHSL[1] = currentColorInHSL[1]*saturationFactor;
|
|
640
|
+
|
|
641
|
+
// CONVERT BACK TO RGB
|
|
642
|
+
let saturatedRGBColor = colorUtils.hslToRgb(currentColorInHSL[0], currentColorInHSL[1], currentColorInHSL[2]);
|
|
643
|
+
|
|
644
|
+
patchObject["color"] = {
|
|
645
|
+
xy: colorUtils.rgbToXy(saturatedRGBColor[0], saturatedRGBColor[1], saturatedRGBColor[2], currentState.info.model.colorGamut)
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// SET GRADIENT
|
|
651
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.gradient != 'undefined' && typeof currentState.payload.gradient != 'undefined')
|
|
652
|
+
{
|
|
653
|
+
let XYColorSet = [];
|
|
654
|
+
|
|
655
|
+
if(typeof msg.payload.gradient.hex != 'undefined' && Array.isArray(msg.payload.gradient.hex) == true)
|
|
426
656
|
{
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
light.effect = 'colorloop';
|
|
436
|
-
|
|
437
|
-
// DISABLE AFTER
|
|
438
|
-
setTimeout(function() {
|
|
439
|
-
light.effect = 'none';
|
|
440
|
-
bridge.client.lights.save(light);
|
|
441
|
-
}, parseFloat(msg.payload.colorloop)*1000);
|
|
657
|
+
XYColorSet = [];
|
|
658
|
+
|
|
659
|
+
for(let oneColor in msg.payload.gradient.hex)
|
|
660
|
+
{
|
|
661
|
+
let rgbFromHex = colorUtils.hexRgb(oneColor);
|
|
662
|
+
XYColorSet.push({
|
|
663
|
+
color: { xy: colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut) }
|
|
664
|
+
});
|
|
442
665
|
}
|
|
443
666
|
}
|
|
444
667
|
|
|
445
|
-
|
|
446
|
-
if(typeof msg.payload != 'undefined' && typeof msg.payload.image != 'undefined' && typeof light.xy != 'undefined')
|
|
668
|
+
if(typeof msg.payload.gradient.rgb != 'undefined' && Array.isArray(msg.payload.gradient.rgb) == true)
|
|
447
669
|
{
|
|
448
|
-
|
|
449
|
-
|
|
670
|
+
XYColorSet = [];
|
|
671
|
+
|
|
672
|
+
for(let oneColor in msg.payload.gradient.rgb)
|
|
450
673
|
{
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
674
|
+
XYColorSet.push({
|
|
675
|
+
color: { xy: colorUtils.rgbToXy(oneColor[0], oneColor[1], oneColor[2], currentState.info.model.colorGamut) }
|
|
676
|
+
});
|
|
454
677
|
}
|
|
455
678
|
}
|
|
456
679
|
|
|
457
|
-
|
|
458
|
-
if((!light.on||!light.reachable)&&isCurrentlyOn==false)
|
|
680
|
+
if(typeof msg.payload.gradient.xyColor != 'undefined' && Array.isArray(msg.payload.gradient.xyColor) == true)
|
|
459
681
|
{
|
|
460
|
-
|
|
461
|
-
futureState = msg;
|
|
682
|
+
XYColorSet = [];
|
|
462
683
|
|
|
463
|
-
|
|
464
|
-
if(typeof futureState.payload != 'undefined')
|
|
684
|
+
for(let oneColor in msg.payload.gradient.xyColor)
|
|
465
685
|
{
|
|
466
|
-
|
|
467
|
-
|
|
686
|
+
XYColorSet.push({
|
|
687
|
+
color: { xy: oneColor }
|
|
688
|
+
});
|
|
468
689
|
}
|
|
690
|
+
}
|
|
469
691
|
|
|
470
|
-
|
|
471
|
-
|
|
692
|
+
patchObject["gradient"] = { points: XYColorSet };
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
//
|
|
696
|
+
// SHOULD PATCH?
|
|
697
|
+
if(Object.values(patchObject).length > 0)
|
|
698
|
+
{
|
|
699
|
+
// IS FOR LATER?
|
|
700
|
+
if(currentState.payload.on === false || currentState.payload.reachable === false)
|
|
701
|
+
{
|
|
702
|
+
if(!patchObject["on"] || !patchObject["on"]["on"])
|
|
472
703
|
{
|
|
473
|
-
|
|
704
|
+
scope.futurePatchState = merge.deep(scope.futurePatchState, patchObject);
|
|
705
|
+
return false;
|
|
474
706
|
}
|
|
475
707
|
}
|
|
476
708
|
|
|
477
|
-
//
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
return light;
|
|
483
|
-
})
|
|
484
|
-
.catch(error => {
|
|
485
|
-
scope.error(error, msg);
|
|
486
|
-
scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
|
|
487
|
-
if(done) { done(error); }
|
|
488
|
-
});
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
709
|
+
// CHANGE NODE UI STATE
|
|
710
|
+
if(config.lightid)
|
|
711
|
+
{
|
|
712
|
+
scope.status({fill: "grey", shape: "ring", text: "hue-light.node.command"});
|
|
713
|
+
}
|
|
492
714
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
715
|
+
// PATCH!
|
|
716
|
+
bridge.patch("light", tempLightID, patchObject)
|
|
717
|
+
.then(function() { if(done) { done(); }})
|
|
718
|
+
.catch(function(errors) { scope.error(errors); });
|
|
719
|
+
}
|
|
720
|
+
else
|
|
721
|
+
{
|
|
722
|
+
// JUST SEND CURRENT STATE
|
|
723
|
+
if(scope.lastCommand !== null)
|
|
724
|
+
{
|
|
725
|
+
currentState.command = scope.lastCommand;
|
|
726
|
+
}
|
|
498
727
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
{
|
|
502
|
-
scope.status({fill: "yellow", shape: "dot", text: RED._("hue-light.node.turned-on-percent",{percent: hueLight.msg.payload.brightness}) });
|
|
503
|
-
}
|
|
504
|
-
else
|
|
505
|
-
{
|
|
506
|
-
scope.status({fill: "grey", shape: "dot", text: "hue-light.node.turned-off"});
|
|
507
|
-
}
|
|
728
|
+
// SEND STATE
|
|
729
|
+
scope.send(currentState);
|
|
508
730
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
if(done) { done(); }
|
|
731
|
+
// RESET LAST COMMAND
|
|
732
|
+
scope.lastCommand = null;
|
|
512
733
|
|
|
513
|
-
|
|
514
|
-
|
|
734
|
+
if(done) { done(); }
|
|
735
|
+
}
|
|
736
|
+
}
|
|
515
737
|
}
|
|
516
|
-
|
|
517
|
-
//
|
|
518
|
-
// CLOSE NODE / REMOVE EVENT LISTENER
|
|
519
|
-
this.on('close', function()
|
|
520
|
-
{
|
|
521
|
-
bridge.events.removeAllListeners('light' + config.lightid);
|
|
522
|
-
});
|
|
523
738
|
}
|
|
524
739
|
|
|
525
740
|
RED.nodes.registerType("hue-light", HueLight);
|
|
526
|
-
}
|
|
741
|
+
}
|