node-red-contrib-huemagic 4.0.4 → 4.2.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/README.md +27 -4
- package/huemagic/hue-bridge-config.html +7 -0
- package/huemagic/hue-bridge-config.js +168 -88
- package/huemagic/hue-brightness.html +15 -1
- package/huemagic/hue-brightness.js +30 -3
- package/huemagic/hue-buttons.html +14 -0
- package/huemagic/hue-buttons.js +5 -0
- package/huemagic/hue-group.html +15 -1
- package/huemagic/hue-group.js +153 -55
- package/huemagic/hue-light.html +15 -1
- package/huemagic/hue-light.js +196 -71
- package/huemagic/hue-motion.html +15 -1
- package/huemagic/hue-motion.js +30 -3
- package/huemagic/hue-rules.html +15 -1
- package/huemagic/hue-rules.js +30 -6
- package/huemagic/hue-scene.html +15 -1
- package/huemagic/hue-scene.js +62 -16
- package/huemagic/hue-temperature.html +15 -1
- package/huemagic/hue-temperature.js +30 -3
- package/huemagic/locales/de/hue-bridge-config.html +8 -0
- package/huemagic/locales/de/hue-group.html +1 -0
- package/huemagic/locales/en-US/hue-bridge-config.html +8 -0
- package/huemagic/locales/en-US/hue-bridge.html +1 -1
- package/huemagic/locales/en-US/hue-group.html +1 -0
- package/huemagic/locales/en-US/hue-light.html +1 -1
- package/huemagic/locales/en-US/hue-magic.html +1 -1
- package/huemagic/utils/api.js +3 -10
- package/huemagic/utils/messages.js +61 -51
- package/package.json +8 -3
package/huemagic/hue-group.js
CHANGED
|
@@ -8,6 +8,7 @@ module.exports = function(RED)
|
|
|
8
8
|
|
|
9
9
|
const scope = this;
|
|
10
10
|
const bridge = RED.nodes.getNode(config.bridge);
|
|
11
|
+
const async = require('async');
|
|
11
12
|
|
|
12
13
|
// EXPORT CONFIG
|
|
13
14
|
this.exportedConfig = config;
|
|
@@ -110,6 +111,11 @@ module.exports = function(RED)
|
|
|
110
111
|
// DEFINE SENSOR ID & CURRENT STATE
|
|
111
112
|
const tempGroupID = (!config.groupid && typeof msg.topic != 'undefined' && bridge.validResourceID.test(msg.topic) === true) ? msg.topic : config.groupid;
|
|
112
113
|
let currentState = bridge.get("group", tempGroupID, { colornames: config.colornamer ? true : false });
|
|
114
|
+
if(!currentState)
|
|
115
|
+
{
|
|
116
|
+
scope.error("The group in not yet available. Please wait until HueMagic has established a connection with the bridge or check whether the resource ID in the configuration is valid.");
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
113
119
|
|
|
114
120
|
// CHECK IF LIGHT ID IS SET
|
|
115
121
|
if(!tempGroupID)
|
|
@@ -153,18 +159,41 @@ module.exports = function(RED)
|
|
|
153
159
|
"bri": msg.payload.brightness ? Math.round((254/100)*msg.payload.brightness) : 254
|
|
154
160
|
};
|
|
155
161
|
|
|
156
|
-
|
|
157
|
-
.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
162
|
+
// PATCH!
|
|
163
|
+
async.retry({
|
|
164
|
+
times: 3,
|
|
165
|
+
errorFilter: function(err) {
|
|
166
|
+
return (err.status == 503);
|
|
167
|
+
},
|
|
168
|
+
interval: function(retryCount) { return retryCount*2000; }
|
|
169
|
+
},
|
|
170
|
+
function(callback, results)
|
|
171
|
+
{
|
|
172
|
+
bridge.patch("group", currentState.info.idV1 + "/action", patchObject, 1)
|
|
173
|
+
.then(function(status) {
|
|
174
|
+
// RESET COLORLOOP ANIMATION AFTER X SECONDS
|
|
175
|
+
setTimeout(function()
|
|
176
|
+
{
|
|
177
|
+
bridge.patch("group", currentState.info.idV1 + "/action", { "effect": "none" }, 1)
|
|
178
|
+
.then(function() { if(done) { done(); }});
|
|
179
|
+
}, parseInt(msg.payload.colorloop) * 1000);
|
|
180
|
+
callback(null, true);
|
|
181
|
+
})
|
|
182
|
+
.catch(function(errors) {
|
|
183
|
+
callback(errors, null);
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
function(errors, success)
|
|
187
|
+
{
|
|
188
|
+
if(errors)
|
|
189
|
+
{
|
|
190
|
+
scope.error(errors);
|
|
191
|
+
scope.status({fill: "red", shape: "ring", text: "hue-group.node.error-input"});
|
|
192
|
+
}
|
|
193
|
+
else if(done)
|
|
194
|
+
{
|
|
195
|
+
done();
|
|
196
|
+
}
|
|
168
197
|
});
|
|
169
198
|
|
|
170
199
|
return false;
|
|
@@ -235,42 +264,65 @@ module.exports = function(RED)
|
|
|
235
264
|
// SET ALERT EFFECT
|
|
236
265
|
patchObject["alert"] = "lselect";
|
|
237
266
|
|
|
238
|
-
//
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
267
|
+
// PATCH!
|
|
268
|
+
async.retry({
|
|
269
|
+
times: 3,
|
|
270
|
+
errorFilter: function(err) {
|
|
271
|
+
return (err.status == 503);
|
|
272
|
+
},
|
|
273
|
+
interval: function(retryCount) { return retryCount*2000; }
|
|
274
|
+
},
|
|
275
|
+
function(callback, results)
|
|
276
|
+
{
|
|
277
|
+
// 1. TURN ON THE LIGHT BULB
|
|
278
|
+
bridge.patch("group", currentState.info.idV1 + "/action", patchObject, 1)
|
|
279
|
+
.then(function(status)
|
|
242
280
|
{
|
|
243
|
-
|
|
244
|
-
var tempPreviousStatePatch = {};
|
|
245
|
-
|
|
246
|
-
tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
|
|
247
|
-
if(tempPreviousState.payload.xyColor)
|
|
248
|
-
{
|
|
249
|
-
tempPreviousStatePatch.xy = [tempPreviousState.payload.xyColor.x, tempPreviousState.payload.xyColor.y];
|
|
250
|
-
}
|
|
251
|
-
else if(tempPreviousState.payload.colorTemp)
|
|
281
|
+
setTimeout(function()
|
|
252
282
|
{
|
|
253
|
-
|
|
254
|
-
|
|
283
|
+
const tempPreviousState = scope.context().get('groupPreviousState');
|
|
284
|
+
var tempPreviousStatePatch = {};
|
|
255
285
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
{
|
|
259
|
-
return bridge.patch("group", currentState.info.idV1 + "/action", { on: false }, 1);
|
|
260
|
-
})
|
|
261
|
-
.then(function(status) {
|
|
262
|
-
if(done) { done(); }
|
|
263
|
-
if(tempPreviousState.payload.on === true)
|
|
286
|
+
tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
|
|
287
|
+
if(tempPreviousState.payload.xyColor)
|
|
264
288
|
{
|
|
265
|
-
|
|
289
|
+
tempPreviousStatePatch.xy = [tempPreviousState.payload.xyColor.x, tempPreviousState.payload.xyColor.y];
|
|
266
290
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
291
|
+
else if(tempPreviousState.payload.colorTemp)
|
|
292
|
+
{
|
|
293
|
+
tempPreviousStatePatch.ct = tempPreviousState.payload.colorTemp;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
bridge.patch("group", currentState.info.idV1 + "/action", tempPreviousStatePatch, 1)
|
|
297
|
+
.then(function(status)
|
|
298
|
+
{
|
|
299
|
+
return bridge.patch("group", currentState.info.idV1 + "/action", { on: false }, 1);
|
|
300
|
+
})
|
|
301
|
+
.then(function(status) {
|
|
302
|
+
if(tempPreviousState.payload.on === true)
|
|
303
|
+
{
|
|
304
|
+
bridge.patch("group", currentState.info.idV1, { on: true }, 1);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
}, parseInt(msg.payload.alert) * 1000);
|
|
308
|
+
|
|
309
|
+
callback(null, true);
|
|
310
|
+
})
|
|
311
|
+
.catch(function(errors) {
|
|
312
|
+
callback(errors, null);
|
|
313
|
+
});
|
|
314
|
+
},
|
|
315
|
+
function(errors, success)
|
|
316
|
+
{
|
|
317
|
+
if(errors)
|
|
318
|
+
{
|
|
319
|
+
scope.error(errors);
|
|
320
|
+
scope.status({fill: "red", shape: "ring", text: "hue-group.node.error-input"});
|
|
321
|
+
}
|
|
322
|
+
else if(done)
|
|
323
|
+
{
|
|
324
|
+
done();
|
|
325
|
+
}
|
|
274
326
|
});
|
|
275
327
|
}
|
|
276
328
|
// ANIMATION STARTED?
|
|
@@ -295,19 +347,44 @@ module.exports = function(RED)
|
|
|
295
347
|
tempPreviousStatePatch.ct = tempPreviousState.payload.colorTemp;
|
|
296
348
|
}
|
|
297
349
|
|
|
298
|
-
|
|
299
|
-
|
|
350
|
+
// PATCH!
|
|
351
|
+
async.retry({
|
|
352
|
+
times: 3,
|
|
353
|
+
errorFilter: function(err) {
|
|
354
|
+
return (err.status == 503);
|
|
355
|
+
},
|
|
356
|
+
interval: function(retryCount) { return retryCount*2000; }
|
|
357
|
+
},
|
|
358
|
+
function(callback, results)
|
|
300
359
|
{
|
|
301
|
-
|
|
360
|
+
bridge.patch("light", currentState.info.lightIds[l], tempPreviousStatePatch).
|
|
361
|
+
then(function(status)
|
|
302
362
|
{
|
|
303
|
-
|
|
363
|
+
if(tempPreviousState.payload.on === false)
|
|
364
|
+
{
|
|
365
|
+
bridge.patch("light", currentState.info.lightIds[l], { on: { on: false } })
|
|
366
|
+
.then(function() { callback(null, true); });
|
|
367
|
+
}
|
|
368
|
+
else
|
|
369
|
+
{
|
|
370
|
+
bridge.patch("light", currentState.info.lightIds[l], { on: { on: false } })
|
|
371
|
+
.then(function(status) {
|
|
372
|
+
callback(null, true);
|
|
373
|
+
return bridge.patch("light", currentState.info.lightIds[l], { on: { on: true } });
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
})
|
|
377
|
+
.catch(function(errors) { callback(errors, null); });
|
|
378
|
+
},
|
|
379
|
+
function(errors, success)
|
|
380
|
+
{
|
|
381
|
+
if(errors)
|
|
382
|
+
{
|
|
383
|
+
scope.error(errors);
|
|
304
384
|
}
|
|
305
|
-
else
|
|
385
|
+
else if(done)
|
|
306
386
|
{
|
|
307
|
-
|
|
308
|
-
.then(function(status) {
|
|
309
|
-
return bridge.patch("light", currentState.info.lightIds[l], { on: { on: true } })
|
|
310
|
-
});
|
|
387
|
+
done();
|
|
311
388
|
}
|
|
312
389
|
});
|
|
313
390
|
}
|
|
@@ -511,9 +588,30 @@ module.exports = function(RED)
|
|
|
511
588
|
}
|
|
512
589
|
|
|
513
590
|
// PATCH!
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
591
|
+
async.retry({
|
|
592
|
+
times: 3,
|
|
593
|
+
errorFilter: function(err) {
|
|
594
|
+
return (err.status == 503);
|
|
595
|
+
},
|
|
596
|
+
interval: function(retryCount) { return retryCount*2000; }
|
|
597
|
+
},
|
|
598
|
+
function(callback, results)
|
|
599
|
+
{
|
|
600
|
+
bridge.patch("group", currentState.info.idV1 + "/action", patchObject, 1)
|
|
601
|
+
.then(function() { callback(null, true); })
|
|
602
|
+
.catch(function(errors) { callback(errors, null); });
|
|
603
|
+
},
|
|
604
|
+
function(errors, success)
|
|
605
|
+
{
|
|
606
|
+
if(errors)
|
|
607
|
+
{
|
|
608
|
+
scope.error(errors);
|
|
609
|
+
}
|
|
610
|
+
else if(done)
|
|
611
|
+
{
|
|
612
|
+
done();
|
|
613
|
+
}
|
|
614
|
+
});
|
|
517
615
|
}
|
|
518
616
|
else
|
|
519
617
|
{
|
package/huemagic/hue-light.html
CHANGED
|
@@ -88,6 +88,19 @@
|
|
|
88
88
|
buttonIcon.removeClass("fa-pencil");
|
|
89
89
|
buttonIcon.addClass("fa-search");
|
|
90
90
|
}
|
|
91
|
+
|
|
92
|
+
function sortResourcesBy(prop, resources)
|
|
93
|
+
{
|
|
94
|
+
return resources.sort((a, b) => {
|
|
95
|
+
if ( a[prop] < b[prop] ){
|
|
96
|
+
return -1;
|
|
97
|
+
}
|
|
98
|
+
if ( a[prop] > b[prop] ){
|
|
99
|
+
return 1;
|
|
100
|
+
}
|
|
101
|
+
return 0;
|
|
102
|
+
});
|
|
103
|
+
}
|
|
91
104
|
|
|
92
105
|
function searchAndSelect()
|
|
93
106
|
{
|
|
@@ -105,6 +118,7 @@
|
|
|
105
118
|
$.get('hue/resources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "light" })
|
|
106
119
|
.done( function(data) {
|
|
107
120
|
var allResources = JSON.parse(data);
|
|
121
|
+
allResources = sortResourcesBy('name', allResources);
|
|
108
122
|
if(allResources.length <= 0)
|
|
109
123
|
{
|
|
110
124
|
notification.close();
|
|
@@ -201,4 +215,4 @@
|
|
|
201
215
|
}
|
|
202
216
|
}
|
|
203
217
|
});
|
|
204
|
-
</script>
|
|
218
|
+
</script>
|
package/huemagic/hue-light.js
CHANGED
|
@@ -8,6 +8,7 @@ module.exports = function(RED)
|
|
|
8
8
|
|
|
9
9
|
const scope = this;
|
|
10
10
|
const bridge = RED.nodes.getNode(config.bridge);
|
|
11
|
+
const async = require('async');
|
|
11
12
|
|
|
12
13
|
// SAVE FUTURE PATCH
|
|
13
14
|
this.futurePatchState = {};
|
|
@@ -123,6 +124,11 @@ module.exports = function(RED)
|
|
|
123
124
|
// DEFINE SENSOR ID & CURRENT STATE
|
|
124
125
|
const tempLightID = (!config.lightid && typeof msg.topic != 'undefined' && bridge.validResourceID.test(msg.topic) === true) ? msg.topic : config.lightid;
|
|
125
126
|
let currentState = bridge.get("light", tempLightID, { colornames: config.colornamer ? true : false });
|
|
127
|
+
if(!currentState)
|
|
128
|
+
{
|
|
129
|
+
scope.error("The light in not yet available. Please wait until HueMagic has established a connection with the bridge or check whether the resource ID in the configuration is valid.");
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
126
132
|
|
|
127
133
|
// CHECK IF LIGHT ID IS SET
|
|
128
134
|
if(!tempLightID)
|
|
@@ -166,18 +172,43 @@ module.exports = function(RED)
|
|
|
166
172
|
"bri": msg.payload.brightness ? Math.round((254/100)*msg.payload.brightness) : currentState.brightnessLevel
|
|
167
173
|
};
|
|
168
174
|
|
|
169
|
-
|
|
170
|
-
.
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
175
|
+
// PATCH!
|
|
176
|
+
async.retry({
|
|
177
|
+
times: 3,
|
|
178
|
+
errorFilter: function(err) {
|
|
179
|
+
return (err.status == 503);
|
|
180
|
+
},
|
|
181
|
+
interval: function(retryCount) { return retryCount*2000; }
|
|
182
|
+
},
|
|
183
|
+
function(callback, results)
|
|
184
|
+
{
|
|
185
|
+
bridge.patch("light", currentState.info.idV1 + "/state", patchObject, 1)
|
|
186
|
+
.then(function(status)
|
|
187
|
+
{
|
|
188
|
+
// RESET COLORLOOP ANIMATION AFTER X SECONDS
|
|
189
|
+
setTimeout(function()
|
|
190
|
+
{
|
|
191
|
+
bridge.patch("light", currentState.info.idV1 + "/state", { "effect": "none" }, 1);
|
|
192
|
+
}, parseInt(msg.payload.colorloop) * 1000);
|
|
193
|
+
|
|
194
|
+
callback(null, true);
|
|
195
|
+
})
|
|
196
|
+
.catch(function(errors)
|
|
197
|
+
{
|
|
198
|
+
callback(errors, null);
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
function(errors, success)
|
|
202
|
+
{
|
|
203
|
+
if(errors)
|
|
204
|
+
{
|
|
205
|
+
scope.error(errors);
|
|
206
|
+
scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
|
|
207
|
+
}
|
|
208
|
+
else if(done)
|
|
209
|
+
{
|
|
210
|
+
done();
|
|
211
|
+
}
|
|
181
212
|
});
|
|
182
213
|
|
|
183
214
|
return false;
|
|
@@ -256,48 +287,72 @@ module.exports = function(RED)
|
|
|
256
287
|
scope.status({fill: "grey", shape: "ring", text: "hue-light.node.command"});
|
|
257
288
|
}
|
|
258
289
|
|
|
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);
|
|
265
|
-
})
|
|
266
|
-
.then(function(status) {
|
|
267
|
-
// 3. RESET PREVIOUS STATE (AFTER X SECONDS)
|
|
268
|
-
setTimeout(function()
|
|
269
|
-
{
|
|
270
|
-
const tempPreviousState = scope.context().get('lightPreviousState');
|
|
271
|
-
var tempPreviousStatePatch = {};
|
|
272
|
-
|
|
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
|
-
}
|
|
282
290
|
|
|
283
|
-
|
|
284
|
-
|
|
291
|
+
// APPLY THE EFFECT
|
|
292
|
+
async.retry({
|
|
293
|
+
times: 3,
|
|
294
|
+
errorFilter: function(err) {
|
|
295
|
+
return (err.status == 503);
|
|
296
|
+
},
|
|
297
|
+
interval: function(retryCount) { return retryCount*2000; }
|
|
298
|
+
},
|
|
299
|
+
function(callback, results)
|
|
300
|
+
{
|
|
301
|
+
// 1. TURN ON THE LIGHT BULB
|
|
302
|
+
bridge.patch("light", tempLightID, patchObject)
|
|
303
|
+
.then(function(status) {
|
|
304
|
+
// 2. APPLY ALERT EFFECT
|
|
305
|
+
const alertEffect = { alert: { action: "breathe" }};
|
|
306
|
+
return bridge.patch("light", tempLightID, alertEffect);
|
|
307
|
+
})
|
|
308
|
+
.then(function(status) {
|
|
309
|
+
// 3. RESET PREVIOUS STATE (AFTER X SECONDS)
|
|
310
|
+
setTimeout(function()
|
|
285
311
|
{
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
if(tempPreviousState.payload.
|
|
312
|
+
const tempPreviousState = scope.context().get('lightPreviousState');
|
|
313
|
+
var tempPreviousStatePatch = {};
|
|
314
|
+
|
|
315
|
+
tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
|
|
316
|
+
if(tempPreviousState.payload.xyColor)
|
|
291
317
|
{
|
|
292
|
-
|
|
293
|
-
.then(function() { if(done) { done(); }});
|
|
318
|
+
tempPreviousStatePatch.color = { xy: tempPreviousState.payload.xyColor };
|
|
294
319
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
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
|
+
return bridge.patch("light", tempLightID, { on: { on: false } })
|
|
329
|
+
.then(function() { if(done) { done(); }});
|
|
330
|
+
})
|
|
331
|
+
.then(function(status) {
|
|
332
|
+
if(tempPreviousState.payload.on === true)
|
|
333
|
+
{
|
|
334
|
+
bridge.patch("light", tempLightID, { on: { on: true } })
|
|
335
|
+
.then(function() { if(done) { done(); }});
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}, parseInt(msg.payload.alert) * 1000);
|
|
339
|
+
callback(null, true);
|
|
340
|
+
})
|
|
341
|
+
.catch(function(errors) {
|
|
342
|
+
callback(errors, null);
|
|
343
|
+
});
|
|
344
|
+
},
|
|
345
|
+
function(errors, success)
|
|
346
|
+
{
|
|
347
|
+
if(errors)
|
|
348
|
+
{
|
|
349
|
+
scope.error(errors);
|
|
350
|
+
scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
|
|
351
|
+
}
|
|
352
|
+
else if(done)
|
|
353
|
+
{
|
|
354
|
+
done();
|
|
355
|
+
}
|
|
301
356
|
});
|
|
302
357
|
}
|
|
303
358
|
// ANIMATION STARTED?
|
|
@@ -322,21 +377,44 @@ module.exports = function(RED)
|
|
|
322
377
|
tempPreviousStatePatch.color_temperature = { mirek: tempPreviousState.payload.colorTemp };
|
|
323
378
|
}
|
|
324
379
|
|
|
325
|
-
|
|
326
|
-
|
|
380
|
+
// PATCH!
|
|
381
|
+
async.retry({
|
|
382
|
+
times: 3,
|
|
383
|
+
errorFilter: function(err) {
|
|
384
|
+
return (err.status == 503);
|
|
385
|
+
},
|
|
386
|
+
interval: function(retryCount) { return retryCount*2000; }
|
|
387
|
+
},
|
|
388
|
+
function(callback, results)
|
|
327
389
|
{
|
|
328
|
-
|
|
390
|
+
bridge.patch("light", tempLightID, tempPreviousStatePatch)
|
|
391
|
+
.then(function(status)
|
|
329
392
|
{
|
|
330
|
-
|
|
331
|
-
|
|
393
|
+
if(tempPreviousState.payload.on === false)
|
|
394
|
+
{
|
|
395
|
+
bridge.patch("light", tempLightID, { on: { on: false } })
|
|
396
|
+
.then(function() { callback(null, true); });
|
|
397
|
+
}
|
|
398
|
+
else
|
|
399
|
+
{
|
|
400
|
+
bridge.patch("light", tempLightID, { on: { on: false } })
|
|
401
|
+
.then(function(status) {
|
|
402
|
+
callback(null, true);
|
|
403
|
+
return bridge.patch("light", tempLightID, { on: { on: true } });
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
})
|
|
407
|
+
.catch(function(errors) { callback(errors, null); });
|
|
408
|
+
},
|
|
409
|
+
function(errors, success)
|
|
410
|
+
{
|
|
411
|
+
if(errors)
|
|
412
|
+
{
|
|
413
|
+
scope.error(errors);
|
|
332
414
|
}
|
|
333
|
-
else
|
|
415
|
+
else if(done)
|
|
334
416
|
{
|
|
335
|
-
|
|
336
|
-
.then(function(status) {
|
|
337
|
-
if(done) { done(); }
|
|
338
|
-
return bridge.patch("light", tempLightID, { on: { on: true } })
|
|
339
|
-
});
|
|
417
|
+
done();
|
|
340
418
|
}
|
|
341
419
|
});
|
|
342
420
|
}
|
|
@@ -608,16 +686,42 @@ module.exports = function(RED)
|
|
|
608
686
|
}
|
|
609
687
|
|
|
610
688
|
// SET DOMINANT COLORS FROM IMAGE
|
|
611
|
-
if(typeof msg.payload != 'undefined' && typeof msg.payload.image != 'undefined' && typeof currentState.payload.xyColor != 'undefined')
|
|
689
|
+
if(typeof msg.payload != 'undefined' && typeof msg.payload.image != 'undefined' && (typeof currentState.payload.xyColor != 'undefined' || typeof currentState.payload.gradient != 'undefined'))
|
|
612
690
|
{
|
|
613
|
-
|
|
691
|
+
let colors = await colorUtils.getColors(msg.payload.image);
|
|
614
692
|
if(colors.length > 0)
|
|
615
693
|
{
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
694
|
+
let colorsHEX = colors.map(color => color.hex());
|
|
695
|
+
|
|
696
|
+
// SET MULTIPLE COLORS ON SUPPORTED LIGHTS
|
|
697
|
+
if(typeof currentState.payload.gradient != 'undefined')
|
|
698
|
+
{
|
|
699
|
+
let XYColorSet = [];
|
|
700
|
+
|
|
701
|
+
for (var i = 0; i < currentState.payload.gradient.totalColors; i++)
|
|
702
|
+
{
|
|
703
|
+
if(typeof colorsHEX[i] != 'undefined')
|
|
704
|
+
{
|
|
705
|
+
let rgbFromHex = colorUtils.hexRgb(colorsHEX[i]);
|
|
706
|
+
XYColorSet.push({
|
|
707
|
+
color: { xy: colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut) }
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
if(XYColorSet.length > 0)
|
|
713
|
+
{
|
|
714
|
+
patchObject["gradient"] = { points: XYColorSet };
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
// SET SINGLE COLOR
|
|
718
|
+
else
|
|
719
|
+
{
|
|
720
|
+
let rgbFromHex = colorUtils.hexRgb(colorsHEX[0]);
|
|
721
|
+
patchObject["color"] = {
|
|
722
|
+
xy: colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut)
|
|
723
|
+
};
|
|
724
|
+
}
|
|
621
725
|
}
|
|
622
726
|
}
|
|
623
727
|
|
|
@@ -713,9 +817,30 @@ module.exports = function(RED)
|
|
|
713
817
|
}
|
|
714
818
|
|
|
715
819
|
// PATCH!
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
820
|
+
async.retry({
|
|
821
|
+
times: 3,
|
|
822
|
+
errorFilter: function(err) {
|
|
823
|
+
return (err.status == 503);
|
|
824
|
+
},
|
|
825
|
+
interval: function(retryCount) { return retryCount*2000; }
|
|
826
|
+
},
|
|
827
|
+
function(callback, results)
|
|
828
|
+
{
|
|
829
|
+
bridge.patch("light", tempLightID, patchObject)
|
|
830
|
+
.then(function() { callback(null, true); })
|
|
831
|
+
.catch(function(errors) { callback(errors, null); });
|
|
832
|
+
},
|
|
833
|
+
function(errors, success)
|
|
834
|
+
{
|
|
835
|
+
if(errors)
|
|
836
|
+
{
|
|
837
|
+
scope.error(errors);
|
|
838
|
+
}
|
|
839
|
+
else if(done)
|
|
840
|
+
{
|
|
841
|
+
done();
|
|
842
|
+
}
|
|
843
|
+
});
|
|
719
844
|
}
|
|
720
845
|
else
|
|
721
846
|
{
|
package/huemagic/hue-motion.html
CHANGED
|
@@ -81,6 +81,19 @@
|
|
|
81
81
|
buttonIcon.removeClass("fa-pencil");
|
|
82
82
|
buttonIcon.addClass("fa-search");
|
|
83
83
|
}
|
|
84
|
+
|
|
85
|
+
function sortResourcesBy(prop, resources)
|
|
86
|
+
{
|
|
87
|
+
return resources.sort((a, b) => {
|
|
88
|
+
if ( a[prop] < b[prop] ){
|
|
89
|
+
return -1;
|
|
90
|
+
}
|
|
91
|
+
if ( a[prop] > b[prop] ){
|
|
92
|
+
return 1;
|
|
93
|
+
}
|
|
94
|
+
return 0;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
84
97
|
|
|
85
98
|
function searchAndSelect()
|
|
86
99
|
{
|
|
@@ -98,6 +111,7 @@
|
|
|
98
111
|
$.get('hue/resources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "motion" })
|
|
99
112
|
.done( function(data) {
|
|
100
113
|
var allResources = JSON.parse(data);
|
|
114
|
+
allResources = sortResourcesBy('name', allResources);
|
|
101
115
|
if(allResources.length <= 0)
|
|
102
116
|
{
|
|
103
117
|
notification.close();
|
|
@@ -194,4 +208,4 @@
|
|
|
194
208
|
}
|
|
195
209
|
}
|
|
196
210
|
});
|
|
197
|
-
</script>
|
|
211
|
+
</script>
|