node-red-contrib-huemagic 2.8.6 → 4.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.
- package/CHANGELOG.md +229 -0
- package/README.md +807 -766
- 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 -320
- 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 -368
- package/huemagic/hue-light.html +133 -59
- package/huemagic/hue-light.js +551 -337
- package/huemagic/hue-magic.html +91 -240
- 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-button.json → hue-buttons.json} +8 -8
- 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-button.json → hue-buttons.json} +11 -5
- 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 +11 -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-button.html +0 -119
- package/huemagic/hue-button.js +0 -94
- 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-button.html +0 -50
- 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-button.html +0 -50
- 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/color.js +0 -9
- package/utils/messages.js +0 -658
- package/utils/rgb.js +0 -188
package/huemagic/hue-light.js
CHANGED
|
@@ -6,22 +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');
|
|
24
|
-
let {randomHexColor} = require('../utils/color');
|
|
19
|
+
const colorUtils = require('./utils/color');
|
|
20
|
+
const merge = require('./utils/merge');
|
|
25
21
|
|
|
26
22
|
//
|
|
27
23
|
// CHECK CONFIG
|
|
@@ -31,365 +27,526 @@ module.exports = function(RED)
|
|
|
31
27
|
return false;
|
|
32
28
|
}
|
|
33
29
|
|
|
30
|
+
//
|
|
31
|
+
// UNIVERSAL MODE?
|
|
32
|
+
if(!config.lightid)
|
|
33
|
+
{
|
|
34
|
+
this.status({fill: "grey", shape: "dot", text: "hue-light.node.universal"});
|
|
35
|
+
}
|
|
36
|
+
|
|
34
37
|
//
|
|
35
38
|
// UPDATE STATE
|
|
36
|
-
if(typeof bridge.disableupdates != 'undefined'||bridge.disableupdates == false)
|
|
39
|
+
if(typeof bridge.disableupdates != 'undefined' || bridge.disableupdates == false)
|
|
37
40
|
{
|
|
38
41
|
this.status({fill: "grey", shape: "dot", text: "hue-light.node.init"});
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
//
|
|
42
|
-
//
|
|
43
|
-
|
|
45
|
+
// SUBSCRIBE TO UPDATES FROM THE BRIDGE
|
|
46
|
+
bridge.subscribe("light", config.lightid, function(info)
|
|
44
47
|
{
|
|
45
|
-
bridge.
|
|
48
|
+
let currentState = bridge.get("light", info.id, { colornames: config.colornamer ? true : false });
|
|
49
|
+
|
|
50
|
+
// RESSOURCE FOUND?
|
|
51
|
+
if(currentState !== false)
|
|
46
52
|
{
|
|
47
|
-
|
|
48
|
-
|
|
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);
|
|
49
64
|
|
|
50
|
-
|
|
51
|
-
|
|
65
|
+
// RESET LAST COMMAND
|
|
66
|
+
scope.lastCommand = null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// NOT IN UNIVERAL MODE? -> CHANGE UI STATES
|
|
70
|
+
if(config.lightid)
|
|
52
71
|
{
|
|
53
|
-
if(
|
|
72
|
+
if(currentState.payload.reachable === true)
|
|
54
73
|
{
|
|
55
|
-
|
|
56
|
-
if(futureState != null)
|
|
74
|
+
if(currentState.payload.on === true)
|
|
57
75
|
{
|
|
58
|
-
|
|
59
|
-
|
|
76
|
+
// APPLY FUTURE STATE COMMANDS
|
|
77
|
+
if(Object.values(scope.futurePatchState).length > 0)
|
|
78
|
+
{
|
|
79
|
+
scope.applyCommands({}, null, null);
|
|
80
|
+
}
|
|
60
81
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
+
}
|
|
66
90
|
}
|
|
67
|
-
// IS SMART PLUG
|
|
68
91
|
else
|
|
69
92
|
{
|
|
70
|
-
|
|
71
|
-
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"});
|
|
72
94
|
}
|
|
73
95
|
}
|
|
74
96
|
else
|
|
75
97
|
{
|
|
76
|
-
|
|
98
|
+
var offNotReachableStatus = RED._("hue-light.node.turned-off") + " (" + RED._("hue-light.node.not-reachable") + ")";
|
|
99
|
+
scope.status({fill: "red", shape: "ring", text: offNotReachableStatus});
|
|
77
100
|
}
|
|
78
101
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
var offNotReachableStatus = RED._("hue-light.node.turned-off") + " (" + RED._("hue-light.node.not-reachable") + ")";
|
|
82
|
-
scope.status({fill: "red", shape: "ring", text: offNotReachableStatus});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// SEND MESSAGE
|
|
86
|
-
if(!config.skipevents) { scope.send(hueLight.msg); }
|
|
87
|
-
|
|
88
|
-
// SAVE LAST STATE
|
|
89
|
-
lastState = light;
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
else
|
|
93
|
-
{
|
|
94
|
-
scope.status({fill: "grey", shape: "dot", text: "hue-light.node.universal"});
|
|
95
|
-
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
96
104
|
|
|
105
|
+
//
|
|
106
|
+
// CONTROL LIGHT
|
|
107
|
+
this.on('input', function(msg, send, done) { scope.applyCommands(msg, send, done); });
|
|
97
108
|
|
|
98
109
|
//
|
|
99
|
-
//
|
|
100
|
-
this.
|
|
110
|
+
// APPLY COMMANDS
|
|
111
|
+
this.applyCommands = async function(msg, send = null, done = null)
|
|
101
112
|
{
|
|
102
|
-
//
|
|
113
|
+
// REDEFINE SEND AND DONE IF NOT AVAILABLE
|
|
103
114
|
send = send || function() { scope.send.apply(scope,arguments); }
|
|
104
|
-
scope.
|
|
105
|
-
});
|
|
115
|
+
done = done || function() { scope.done.apply(scope,arguments); }
|
|
106
116
|
|
|
117
|
+
// SAVE LAST COMMAND
|
|
118
|
+
scope.lastCommand = msg;
|
|
107
119
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
120
|
+
// CREATE PATCH
|
|
121
|
+
let patchObject = {};
|
|
122
|
+
|
|
123
|
+
// DEFINE SENSOR ID & CURRENT STATE
|
|
124
|
+
const tempLightID = (typeof msg.topic != 'undefined' && msg.topic.length > 0) ? msg.topic : config.lightid;
|
|
125
|
+
let currentState = bridge.get("light", tempLightID, { colornames: config.colornamer ? true : false });
|
|
113
126
|
|
|
114
127
|
// CHECK IF LIGHT ID IS SET
|
|
115
|
-
if(tempLightID
|
|
128
|
+
if(!tempLightID)
|
|
116
129
|
{
|
|
117
130
|
scope.error(RED._("hue-light.node.error-no-id"));
|
|
118
131
|
return false;
|
|
119
132
|
}
|
|
120
133
|
|
|
121
134
|
// GET CURRENT STATE
|
|
122
|
-
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") )
|
|
123
136
|
{
|
|
124
|
-
|
|
125
|
-
.
|
|
126
|
-
|
|
127
|
-
|
|
137
|
+
// SET LAST COMMAND
|
|
138
|
+
if(scope.lastCommand !== null)
|
|
139
|
+
{
|
|
140
|
+
currentState.command = scope.lastCommand;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// SEND STATE
|
|
144
|
+
scope.send(currentState);
|
|
128
145
|
|
|
146
|
+
// RESET LAST COMMAND
|
|
147
|
+
scope.lastCommand = null;
|
|
148
|
+
|
|
149
|
+
if(done) { done(); }
|
|
129
150
|
return true;
|
|
130
151
|
}
|
|
131
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
|
+
|
|
132
186
|
// ALERT EFFECT
|
|
133
187
|
if(typeof msg.payload != 'undefined' && typeof msg.payload.alert != 'undefined' && msg.payload.alert > 0)
|
|
134
188
|
{
|
|
135
|
-
|
|
136
|
-
.
|
|
137
|
-
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);
|
|
138
191
|
|
|
139
|
-
|
|
140
|
-
|
|
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')
|
|
141
217
|
{
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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))
|
|
147
228
|
{
|
|
148
|
-
|
|
149
|
-
|
|
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);
|
|
150
232
|
}
|
|
151
|
-
else
|
|
233
|
+
else
|
|
152
234
|
{
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
var randomColor = randomHexColor();
|
|
156
|
-
var rgbResult = hexRGB(randomColor);
|
|
157
|
-
light.xy = rgb.convertRGBtoXY([rgbResult.red, rgbResult.green, rgbResult.blue], light.model.id);
|
|
158
|
-
}
|
|
159
|
-
else
|
|
235
|
+
var colorHex = colorUtils.colornames(msg.payload.color);
|
|
236
|
+
if(colorHex)
|
|
160
237
|
{
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
{
|
|
164
|
-
var rgbResult = hexRGB(colorHex);
|
|
165
|
-
light.xy = rgb.convertRGBtoXY([rgbResult.red, rgbResult.green, rgbResult.blue], light.model.id);
|
|
166
|
-
}
|
|
238
|
+
let rgbFromHex = colorUtils.hexRgb(colorHex);
|
|
239
|
+
XYAlertColor = colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut);
|
|
167
240
|
}
|
|
168
241
|
}
|
|
169
|
-
else
|
|
170
|
-
{
|
|
171
|
-
light.xy = rgb.convertRGBtoXY([255,0,0], light.model.id);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// ACTIVATE
|
|
176
|
-
light.on = true;
|
|
177
|
-
light.brightness = 254;
|
|
178
|
-
light.transitionTime = 0;
|
|
179
|
-
return bridge.client.lights.save(light);
|
|
180
|
-
})
|
|
181
|
-
.then(light => {
|
|
182
|
-
if(!config.lightid) { scope.sendLightStatus(light, send, done); }
|
|
183
|
-
return light;
|
|
184
|
-
})
|
|
185
|
-
.then(light => {
|
|
186
|
-
// ACTIVATE ALERT
|
|
187
|
-
if(light != false)
|
|
188
|
-
{
|
|
189
|
-
light.alert = 'lselect';
|
|
190
|
-
return bridge.client.lights.save(light);
|
|
191
242
|
}
|
|
192
243
|
else
|
|
193
244
|
{
|
|
194
|
-
|
|
245
|
+
XYAlertColor = colorUtils.rgbToXy(255, 0, 0, currentState.info.model.colorGamut);
|
|
195
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);
|
|
196
265
|
})
|
|
197
|
-
.then(
|
|
198
|
-
//
|
|
199
|
-
|
|
266
|
+
.then(function(status) {
|
|
267
|
+
// 3. RESET PREVIOUS STATE (AFTER X SECONDS)
|
|
268
|
+
setTimeout(function()
|
|
200
269
|
{
|
|
201
|
-
|
|
202
|
-
var
|
|
270
|
+
const tempPreviousState = scope.context().get('lightPreviousState');
|
|
271
|
+
var tempPreviousStatePatch = {};
|
|
203
272
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
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
|
+
}
|
|
209
282
|
|
|
210
|
-
|
|
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)
|
|
211
291
|
{
|
|
212
|
-
light
|
|
292
|
+
bridge.patch("light", tempLightID, { on: { on: true } })
|
|
293
|
+
.then(function() { if(done) { done(); }});
|
|
213
294
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}, alertSeconds * 1000);
|
|
217
|
-
}
|
|
295
|
+
});
|
|
296
|
+
}, parseInt(msg.payload.alert) * 1000);
|
|
218
297
|
})
|
|
219
|
-
.catch(
|
|
220
|
-
scope.error(
|
|
298
|
+
.catch(function(errors) {
|
|
299
|
+
scope.error(errors);
|
|
221
300
|
scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
|
|
222
|
-
if(done) { done(error); }
|
|
223
301
|
});
|
|
224
302
|
}
|
|
225
303
|
// ANIMATION STARTED?
|
|
226
304
|
else if(typeof msg.animation != 'undefined' && msg.animation.status == true && msg.animation.restore == true)
|
|
227
305
|
{
|
|
228
|
-
|
|
229
|
-
.
|
|
230
|
-
scope.context().set('lightPreviousState', [(light.on) ? true : false, light.brightness, light.xy ? light.xy : false]);
|
|
231
|
-
})
|
|
232
|
-
.catch(error => {
|
|
233
|
-
scope.error(error, msg);
|
|
234
|
-
scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
|
|
235
|
-
if(done) { done(error); }
|
|
236
|
-
});
|
|
306
|
+
// SAVE PREVIOUS STATE
|
|
307
|
+
scope.context().set('lightPreviousState', currentState);
|
|
237
308
|
}
|
|
238
309
|
// ANIMATION STOPPED AND RESTORE ACTIVE?
|
|
239
310
|
else if(typeof msg.animation != 'undefined' && msg.animation.status == false && msg.animation.restore == true)
|
|
240
311
|
{
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
var lightPreviousState = scope.context().get('lightPreviousState');
|
|
244
|
-
light.on = lightPreviousState[0];
|
|
245
|
-
light.alert = 'none';
|
|
246
|
-
light.brightness = lightPreviousState[1];
|
|
247
|
-
light.transitionTime = 2;
|
|
312
|
+
const tempPreviousState = scope.context().get('lightPreviousState');
|
|
313
|
+
var tempPreviousStatePatch = {};
|
|
248
314
|
|
|
249
|
-
|
|
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)
|
|
250
329
|
{
|
|
251
|
-
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
|
+
});
|
|
252
340
|
}
|
|
253
|
-
|
|
254
|
-
bridge.client.lights.save(light);
|
|
255
|
-
})
|
|
256
|
-
.catch(error => {
|
|
257
|
-
scope.error(error, msg);
|
|
258
|
-
scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
|
|
259
|
-
if(done) { done(error); }
|
|
260
341
|
});
|
|
261
342
|
}
|
|
262
|
-
// EXTENDED
|
|
343
|
+
// EXTENDED COMMANDS
|
|
263
344
|
else
|
|
264
345
|
{
|
|
265
|
-
|
|
266
|
-
.
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
// SET LIGHT STATE SIMPLE MODE
|
|
271
|
-
if(msg.payload === true||msg.payload === false)
|
|
272
|
-
{
|
|
273
|
-
var command = msg.payload;
|
|
274
|
-
msg.payload = {
|
|
275
|
-
on: command
|
|
276
|
-
};
|
|
277
|
-
}
|
|
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
|
+
}
|
|
278
351
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
+
}
|
|
284
357
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
358
|
+
// TOGGLE ON / OFF
|
|
359
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.toggle != 'undefined')
|
|
360
|
+
{
|
|
361
|
+
patchObject["on"] = { on: !currentState.payload.on };
|
|
362
|
+
}
|
|
288
363
|
|
|
289
|
-
|
|
290
|
-
|
|
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))
|
|
291
369
|
{
|
|
292
|
-
|
|
293
|
-
|
|
370
|
+
let ct = colorUtils.colorTemperature();
|
|
371
|
+
let autoBrightness = ((300-ct)/2)+100;
|
|
372
|
+
autoBrightness = (autoBrightness > 100) ? 100 : autoBrightness;
|
|
373
|
+
autoBrightness = (autoBrightness < 20) ? 20 : autoBrightness;
|
|
294
374
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
{
|
|
298
|
-
light.on = light.on ? false : true;
|
|
375
|
+
// SET CALCULATED BRIGHTNESS
|
|
376
|
+
patchObject["dimming"] = { brightness: autoBrightness };
|
|
299
377
|
}
|
|
300
|
-
|
|
301
|
-
// SET BRIGHTNESS
|
|
302
|
-
if(typeof msg.payload != 'undefined' && typeof msg.payload.brightness != 'undefined')
|
|
378
|
+
else
|
|
303
379
|
{
|
|
304
|
-
if(msg.payload.brightness > 100 ||
|
|
380
|
+
if(msg.payload.brightness > 100 || msg.payload.brightness < 0)
|
|
305
381
|
{
|
|
306
382
|
scope.error("Invalid brightness setting. Only 0 - 100 percent allowed");
|
|
307
383
|
return false;
|
|
308
384
|
}
|
|
309
385
|
else if(msg.payload.brightness == 0)
|
|
310
386
|
{
|
|
311
|
-
|
|
387
|
+
if(currentState.payload.on !== false) { patchObject["on"] = { on: false }; }
|
|
312
388
|
}
|
|
313
389
|
else
|
|
314
390
|
{
|
|
315
|
-
|
|
316
|
-
light.brightness = Math.round((254/100)*parseInt(msg.payload.brightness));
|
|
391
|
+
patchObject["dimming"] = { brightness: msg.payload.brightness };
|
|
317
392
|
}
|
|
318
393
|
}
|
|
319
|
-
|
|
394
|
+
}
|
|
395
|
+
else if(typeof msg.payload != 'undefined' && typeof msg.payload.brightnessLevel != 'undefined')
|
|
396
|
+
{
|
|
397
|
+
if(msg.payload.brightnessLevel > 254 || msg.payload.brightnessLevel < 0)
|
|
320
398
|
{
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
scope.error("Invalid brightness setting. Only 0 - 254 allowed");
|
|
324
|
-
return false;
|
|
325
|
-
}
|
|
326
|
-
else if(msg.payload.brightness == 0)
|
|
327
|
-
{
|
|
328
|
-
light.on = false;
|
|
329
|
-
}
|
|
330
|
-
else
|
|
331
|
-
{
|
|
332
|
-
light.on = true;
|
|
333
|
-
light.brightness = parseInt(msg.payload.brightnessLevel);
|
|
334
|
-
}
|
|
399
|
+
scope.error("Invalid brightness setting. Only 0 - 254 allowed");
|
|
400
|
+
return false;
|
|
335
401
|
}
|
|
336
|
-
else if(
|
|
402
|
+
else if(msg.payload.brightness == 0)
|
|
337
403
|
{
|
|
338
|
-
if
|
|
339
|
-
{
|
|
340
|
-
light.on = true;
|
|
341
|
-
}
|
|
342
|
-
light.incrementBrightness = Math.round((254/100)*parseInt(msg.payload.incrementBrightness));
|
|
404
|
+
if(currentState.payload.on !== false) { patchObject["on"] = { on: false }; }
|
|
343
405
|
}
|
|
344
|
-
else
|
|
406
|
+
else
|
|
345
407
|
{
|
|
346
|
-
|
|
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)
|
|
347
448
|
{
|
|
348
|
-
|
|
449
|
+
let rgbFromHex = colorUtils.hexRgb(colorHex);
|
|
450
|
+
XYAlertColor = colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut);
|
|
349
451
|
}
|
|
350
|
-
light.incrementBrightness = Math.round((254/100)*parseInt(msg.payload.decrementBrightness))*-1;
|
|
351
452
|
}
|
|
352
453
|
|
|
353
|
-
|
|
354
|
-
|
|
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')
|
|
355
490
|
{
|
|
356
|
-
if(new RegExp("random|any|whatever").test(msg.payload.color))
|
|
491
|
+
if(new RegExp("random|any|whatever").test(msg.payload.mixColor.color))
|
|
357
492
|
{
|
|
358
|
-
|
|
359
|
-
var rgbResult = hexRGB(randomColor);
|
|
360
|
-
light.xy = rgb.convertRGBtoXY([rgbResult.red, rgbResult.green, rgbResult.blue], light.model.id);
|
|
493
|
+
RGBColor = colorUtils.hexRgb(colorUtils.randomHexColor());
|
|
361
494
|
}
|
|
362
495
|
else
|
|
363
496
|
{
|
|
364
|
-
var colorHex = colornames(msg.payload.color);
|
|
497
|
+
var colorHex = colorUtils.colornames(msg.payload.mixColor.color);
|
|
365
498
|
if(colorHex)
|
|
366
499
|
{
|
|
367
|
-
|
|
368
|
-
light.xy = rgb.convertRGBtoXY([rgbResult.red, rgbResult.green, rgbResult.blue], light.model.id);
|
|
500
|
+
RGBColor = colorUtils.hexRgb(colorHex);
|
|
369
501
|
}
|
|
370
502
|
}
|
|
371
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
|
+
}
|
|
372
516
|
|
|
373
|
-
//
|
|
374
|
-
|
|
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)
|
|
375
520
|
{
|
|
376
|
-
|
|
521
|
+
mixingAmount = msg.payload.mixColor.amount/100;
|
|
377
522
|
}
|
|
378
523
|
|
|
379
|
-
//
|
|
380
|
-
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
|
|
381
533
|
{
|
|
382
|
-
|
|
383
|
-
|
|
534
|
+
patchObject["color"] = {
|
|
535
|
+
xy: colorUtils.rgbToXy(RGBColor[0], RGBColor[1], RGBColor[2], currentState.info.model.colorGamut)
|
|
536
|
+
};
|
|
384
537
|
}
|
|
538
|
+
}
|
|
385
539
|
|
|
386
|
-
|
|
387
|
-
|
|
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))
|
|
388
545
|
{
|
|
389
546
|
let colorTemp = parseInt(msg.payload.colorTemp);
|
|
390
547
|
if(colorTemp >= 153 && colorTemp <= 500)
|
|
391
548
|
{
|
|
392
|
-
|
|
549
|
+
patchObject["color_temperature"] = { mirek: colorTemp };
|
|
393
550
|
}
|
|
394
551
|
else
|
|
395
552
|
{
|
|
@@ -397,131 +554,188 @@ module.exports = function(RED)
|
|
|
397
554
|
return false;
|
|
398
555
|
}
|
|
399
556
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
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;
|
|
404
585
|
|
|
405
|
-
// SET
|
|
406
|
-
|
|
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)
|
|
407
615
|
{
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
}
|
|
413
|
-
else
|
|
414
|
-
{
|
|
415
|
-
light.saturation = Math.round((254/100)*parseInt(msg.payload.saturation));
|
|
416
|
-
}
|
|
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
|
+
};
|
|
417
621
|
}
|
|
622
|
+
}
|
|
418
623
|
|
|
419
|
-
|
|
420
|
-
|
|
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)
|
|
421
628
|
{
|
|
422
|
-
|
|
629
|
+
scope.error("Invalid saturation setting. Only 0 - 100 allowed");
|
|
630
|
+
return false;
|
|
423
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);
|
|
424
637
|
|
|
425
|
-
|
|
426
|
-
|
|
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)
|
|
427
656
|
{
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
light.effect = 'colorloop';
|
|
437
|
-
|
|
438
|
-
// DISABLE AFTER
|
|
439
|
-
setTimeout(function() {
|
|
440
|
-
light.effect = 'none';
|
|
441
|
-
bridge.client.lights.save(light);
|
|
442
|
-
}, 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
|
+
});
|
|
443
665
|
}
|
|
444
666
|
}
|
|
445
667
|
|
|
446
|
-
|
|
447
|
-
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)
|
|
448
669
|
{
|
|
449
|
-
|
|
450
|
-
|
|
670
|
+
XYColorSet = [];
|
|
671
|
+
|
|
672
|
+
for(let oneColor in msg.payload.gradient.rgb)
|
|
451
673
|
{
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
674
|
+
XYColorSet.push({
|
|
675
|
+
color: { xy: colorUtils.rgbToXy(oneColor[0], oneColor[1], oneColor[2], currentState.info.model.colorGamut) }
|
|
676
|
+
});
|
|
455
677
|
}
|
|
456
678
|
}
|
|
457
679
|
|
|
458
|
-
|
|
459
|
-
if((!light.on||!light.reachable)&&isCurrentlyOn==false)
|
|
680
|
+
if(typeof msg.payload.gradient.xyColor != 'undefined' && Array.isArray(msg.payload.gradient.xyColor) == true)
|
|
460
681
|
{
|
|
461
|
-
|
|
462
|
-
futureState = msg;
|
|
682
|
+
XYColorSet = [];
|
|
463
683
|
|
|
464
|
-
|
|
465
|
-
if(typeof futureState.payload != 'undefined')
|
|
684
|
+
for(let oneColor in msg.payload.gradient.xyColor)
|
|
466
685
|
{
|
|
467
|
-
|
|
468
|
-
|
|
686
|
+
XYColorSet.push({
|
|
687
|
+
color: { xy: oneColor }
|
|
688
|
+
});
|
|
469
689
|
}
|
|
690
|
+
}
|
|
470
691
|
|
|
471
|
-
|
|
472
|
-
|
|
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"])
|
|
473
703
|
{
|
|
474
|
-
|
|
704
|
+
scope.futurePatchState = merge.deep(scope.futurePatchState, patchObject);
|
|
705
|
+
return false;
|
|
475
706
|
}
|
|
476
707
|
}
|
|
477
708
|
|
|
478
|
-
//
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
return light;
|
|
484
|
-
})
|
|
485
|
-
.catch(error => {
|
|
486
|
-
scope.error(error, msg);
|
|
487
|
-
scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
|
|
488
|
-
if(done) { done(error); }
|
|
489
|
-
});
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
709
|
+
// CHANGE NODE UI STATE
|
|
710
|
+
if(config.lightid)
|
|
711
|
+
{
|
|
712
|
+
scope.status({fill: "grey", shape: "ring", text: "hue-light.node.command"});
|
|
713
|
+
}
|
|
493
714
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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
|
+
}
|
|
499
727
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
{
|
|
503
|
-
scope.status({fill: "yellow", shape: "dot", text: RED._("hue-light.node.turned-on-percent",{percent: hueLight.msg.payload.brightness}) });
|
|
504
|
-
}
|
|
505
|
-
else
|
|
506
|
-
{
|
|
507
|
-
scope.status({fill: "grey", shape: "dot", text: "hue-light.node.turned-off"});
|
|
508
|
-
}
|
|
728
|
+
// SEND STATE
|
|
729
|
+
scope.send(currentState);
|
|
509
730
|
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
if(done) { done(); }
|
|
731
|
+
// RESET LAST COMMAND
|
|
732
|
+
scope.lastCommand = null;
|
|
513
733
|
|
|
514
|
-
|
|
515
|
-
|
|
734
|
+
if(done) { done(); }
|
|
735
|
+
}
|
|
736
|
+
}
|
|
516
737
|
}
|
|
517
|
-
|
|
518
|
-
//
|
|
519
|
-
// CLOSE NODE / REMOVE EVENT LISTENER
|
|
520
|
-
this.on('close', function()
|
|
521
|
-
{
|
|
522
|
-
bridge.events.removeAllListeners('light' + config.lightid);
|
|
523
|
-
});
|
|
524
738
|
}
|
|
525
739
|
|
|
526
740
|
RED.nodes.registerType("hue-light", HueLight);
|
|
527
|
-
}
|
|
741
|
+
}
|