node-red-contrib-huemagic 4.1.0 → 4.2.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.
@@ -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;
@@ -112,7 +113,7 @@ module.exports = function(RED)
112
113
  let currentState = bridge.get("group", tempGroupID, { colornames: config.colornamer ? true : false });
113
114
  if(!currentState)
114
115
  {
115
- 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..");
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.");
116
117
  return false;
117
118
  }
118
119
 
@@ -158,18 +159,41 @@ module.exports = function(RED)
158
159
  "bri": msg.payload.brightness ? Math.round((254/100)*msg.payload.brightness) : 254
159
160
  };
160
161
 
161
- bridge.patch("group", currentState.info.idV1 + "/action", patchObject, 1)
162
- .then(function(status) {
163
- // RESET COLORLOOP ANIMATION AFTER X SECONDS
164
- setTimeout(function()
165
- {
166
- bridge.patch("group", currentState.info.idV1 + "/action", { "effect": "none" }, 1)
167
- .then(function() { if(done) { done(); }});
168
- }, parseInt(msg.payload.colorloop) * 1000);
169
- })
170
- .catch(function(errors) {
171
- scope.error(errors);
172
- scope.status({fill: "red", shape: "ring", text: "hue-group.node.error-input"});
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
+ }
173
197
  });
174
198
 
175
199
  return false;
@@ -240,42 +264,65 @@ module.exports = function(RED)
240
264
  // SET ALERT EFFECT
241
265
  patchObject["alert"] = "lselect";
242
266
 
243
- // 1. TURN ON THE LIGHT BULB
244
- bridge.patch("group", currentState.info.idV1 + "/action", patchObject, 1)
245
- .then(function(status) {
246
- setTimeout(function()
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)
247
280
  {
248
- const tempPreviousState = scope.context().get('groupPreviousState');
249
- var tempPreviousStatePatch = {};
250
-
251
- tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
252
- if(tempPreviousState.payload.xyColor)
253
- {
254
- tempPreviousStatePatch.xy = [tempPreviousState.payload.xyColor.x, tempPreviousState.payload.xyColor.y];
255
- }
256
- else if(tempPreviousState.payload.colorTemp)
281
+ setTimeout(function()
257
282
  {
258
- tempPreviousStatePatch.ct = tempPreviousState.payload.colorTemp;
259
- }
283
+ const tempPreviousState = scope.context().get('groupPreviousState');
284
+ var tempPreviousStatePatch = {};
260
285
 
261
- bridge.patch("group", currentState.info.idV1 + "/action", tempPreviousStatePatch, 1)
262
- .then(function(status)
263
- {
264
- return bridge.patch("group", currentState.info.idV1 + "/action", { on: false }, 1);
265
- })
266
- .then(function(status) {
267
- if(done) { done(); }
268
- if(tempPreviousState.payload.on === true)
286
+ tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
287
+ if(tempPreviousState.payload.xyColor)
269
288
  {
270
- bridge.patch("group", currentState.info.idV1, { on: true }, 1);
289
+ tempPreviousStatePatch.xy = [tempPreviousState.payload.xyColor.x, tempPreviousState.payload.xyColor.y];
271
290
  }
272
- });
273
- }, parseInt(msg.payload.alert) * 1000);
274
- })
275
- .catch(function(errors) {
276
- scope.error(errors);
277
- scope.status({fill: "red", shape: "ring", text: "hue-group.node.error-input"});
278
- if(done) { done(error); }
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
+ }
279
326
  });
280
327
  }
281
328
  // ANIMATION STARTED?
@@ -300,19 +347,44 @@ module.exports = function(RED)
300
347
  tempPreviousStatePatch.ct = tempPreviousState.payload.colorTemp;
301
348
  }
302
349
 
303
- bridge.patch("light", currentState.info.lightIds[l], tempPreviousStatePatch).
304
- then(function(status)
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)
305
359
  {
306
- if(tempPreviousState.payload.on === false)
360
+ bridge.patch("light", currentState.info.lightIds[l], tempPreviousStatePatch).
361
+ then(function(status)
307
362
  {
308
- bridge.patch("light", currentState.info.lightIds[l], { on: { on: false } })
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);
309
384
  }
310
- else
385
+ else if(done)
311
386
  {
312
- bridge.patch("light", currentState.info.lightIds[l], { on: { on: false } })
313
- .then(function(status) {
314
- return bridge.patch("light", currentState.info.lightIds[l], { on: { on: true } })
315
- });
387
+ done();
316
388
  }
317
389
  });
318
390
  }
@@ -516,9 +588,30 @@ module.exports = function(RED)
516
588
  }
517
589
 
518
590
  // PATCH!
519
- bridge.patch("group", currentState.info.idV1 + "/action", patchObject, 1)
520
- .then(function() { if(done) { done(); }})
521
- .catch(function(errors) { scope.error(errors); });
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
+ });
522
615
  }
523
616
  else
524
617
  {
@@ -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 = {};
@@ -125,7 +126,7 @@ module.exports = function(RED)
125
126
  let currentState = bridge.get("light", tempLightID, { colornames: config.colornamer ? true : false });
126
127
  if(!currentState)
127
128
  {
128
- 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..");
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.");
129
130
  return false;
130
131
  }
131
132
 
@@ -171,18 +172,43 @@ module.exports = function(RED)
171
172
  "bri": msg.payload.brightness ? Math.round((254/100)*msg.payload.brightness) : currentState.brightnessLevel
172
173
  };
173
174
 
174
- bridge.patch("light", currentState.info.idV1 + "/state", patchObject, 1)
175
- .then(function(status) {
176
- // RESET COLORLOOP ANIMATION AFTER X SECONDS
177
- setTimeout(function()
178
- {
179
- bridge.patch("light", currentState.info.idV1 + "/state", { "effect": "none" }, 1);
180
- if(done) { done(); }
181
- }, parseInt(msg.payload.colorloop) * 1000);
182
- })
183
- .catch(function(errors) {
184
- scope.error(errors);
185
- scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
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
+ }
186
212
  });
187
213
 
188
214
  return false;
@@ -261,48 +287,72 @@ module.exports = function(RED)
261
287
  scope.status({fill: "grey", shape: "ring", text: "hue-light.node.command"});
262
288
  }
263
289
 
264
- // 1. TURN ON THE LIGHT BULB
265
- bridge.patch("light", tempLightID, patchObject)
266
- .then(function(status) {
267
- // 2. APPLY ALERT EFFECT
268
- const alertEffect = { alert: { action: "breathe" }};
269
- return bridge.patch("light", tempLightID, alertEffect);
270
- })
271
- .then(function(status) {
272
- // 3. RESET PREVIOUS STATE (AFTER X SECONDS)
273
- setTimeout(function()
274
- {
275
- const tempPreviousState = scope.context().get('lightPreviousState');
276
- var tempPreviousStatePatch = {};
277
-
278
- tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
279
- if(tempPreviousState.payload.xyColor)
280
- {
281
- tempPreviousStatePatch.color = { xy: tempPreviousState.payload.xyColor };
282
- }
283
- else if(tempPreviousState.payload.colorTemp)
284
- {
285
- tempPreviousStatePatch.color_temperature = { mirek: tempPreviousState.payload.colorTemp };
286
- }
287
290
 
288
- bridge.patch("light", tempLightID, tempPreviousStatePatch).
289
- then(function(status)
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()
290
311
  {
291
- return bridge.patch("light", tempLightID, { on: { on: false } })
292
- .then(function() { if(done) { done(); }});
293
- })
294
- .then(function(status) {
295
- if(tempPreviousState.payload.on === true)
312
+ const tempPreviousState = scope.context().get('lightPreviousState');
313
+ var tempPreviousStatePatch = {};
314
+
315
+ tempPreviousStatePatch.dimming = { brightness: tempPreviousState.payload.brightness };
316
+ if(tempPreviousState.payload.xyColor)
296
317
  {
297
- bridge.patch("light", tempLightID, { on: { on: true } })
298
- .then(function() { if(done) { done(); }});
318
+ tempPreviousStatePatch.color = { xy: tempPreviousState.payload.xyColor };
319
+ }
320
+ else if(tempPreviousState.payload.colorTemp)
321
+ {
322
+ tempPreviousStatePatch.color_temperature = { mirek: tempPreviousState.payload.colorTemp };
299
323
  }
300
- });
301
- }, parseInt(msg.payload.alert) * 1000);
302
- })
303
- .catch(function(errors) {
304
- scope.error(errors);
305
- scope.status({fill: "red", shape: "ring", text: "hue-light.node.error-input"});
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
+ }
306
356
  });
307
357
  }
308
358
  // ANIMATION STARTED?
@@ -327,21 +377,44 @@ module.exports = function(RED)
327
377
  tempPreviousStatePatch.color_temperature = { mirek: tempPreviousState.payload.colorTemp };
328
378
  }
329
379
 
330
- bridge.patch("light", tempLightID, tempPreviousStatePatch).
331
- then(function(status)
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)
332
389
  {
333
- if(tempPreviousState.payload.on === false)
390
+ bridge.patch("light", tempLightID, tempPreviousStatePatch)
391
+ .then(function(status)
334
392
  {
335
- bridge.patch("light", tempLightID, { on: { on: false } })
336
- .then(function() { if(done) { done(); }});
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);
337
414
  }
338
- else
415
+ else if(done)
339
416
  {
340
- bridge.patch("light", tempLightID, { on: { on: false } })
341
- .then(function(status) {
342
- if(done) { done(); }
343
- return bridge.patch("light", tempLightID, { on: { on: true } })
344
- });
417
+ done();
345
418
  }
346
419
  });
347
420
  }
@@ -613,16 +686,42 @@ module.exports = function(RED)
613
686
  }
614
687
 
615
688
  // SET DOMINANT COLORS FROM IMAGE
616
- 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'))
617
690
  {
618
- var colors = await colorUtils.getColors(msg.payload.image);
691
+ let colors = await colorUtils.getColors(msg.payload.image);
619
692
  if(colors.length > 0)
620
693
  {
621
- var colorsHEX = colors.map(color => color.hex());
622
- let rgbFromHex = colorUtils.hexRgb(colorsHEX[0]);
623
- patchObject["color"] = {
624
- xy: colorUtils.rgbToXy(rgbFromHex[0], rgbFromHex[1], rgbFromHex[2], currentState.info.model.colorGamut)
625
- };
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
+ }
626
725
  }
627
726
  }
628
727
 
@@ -718,9 +817,30 @@ module.exports = function(RED)
718
817
  }
719
818
 
720
819
  // PATCH!
721
- bridge.patch("light", tempLightID, patchObject)
722
- .then(function() { if(done) { done(); }})
723
- .catch(function(errors) { scope.error(errors); });
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
+ });
724
844
  }
725
845
  else
726
846
  {
@@ -52,8 +52,6 @@
52
52
  {
53
53
  position: relative;
54
54
  cursor: pointer;
55
-
56
- border-radius: 20px;
57
55
  overflow: hidden;
58
56
 
59
57
  border: 2px solid #fff;
@@ -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 LAST COMMAND
13
14
  this.lastCommand = null;
@@ -110,7 +111,7 @@ module.exports = function(RED)
110
111
  let currentState = bridge.get("motion", tempSensorID);
111
112
  if(!currentState)
112
113
  {
113
- scope.error("The sensor 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..");
114
+ scope.error("The sensor 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.");
114
115
  return false;
115
116
  }
116
117
 
@@ -151,9 +152,30 @@ module.exports = function(RED)
151
152
  }
152
153
 
153
154
  // PATCH!
154
- bridge.patch("motion", tempSensorID, patchObject)
155
- .then(function() { if(done) { done(); }})
156
- .catch(function(errors) { scope.error(errors); });
155
+ async.retry({
156
+ times: 3,
157
+ errorFilter: function(err) {
158
+ return (err.status == 503);
159
+ },
160
+ interval: function(retryCount) { return retryCount*2000; }
161
+ },
162
+ function(callback, results)
163
+ {
164
+ bridge.patch("motion", tempSensorID, patchObject)
165
+ .then(function() { if(done) { callback(null, true); }})
166
+ .catch(function(errors) { callback(errors, null); });
167
+ },
168
+ function(errors, success)
169
+ {
170
+ if(errors)
171
+ {
172
+ scope.error(errors);
173
+ }
174
+ else if(done)
175
+ {
176
+ done();
177
+ }
178
+ });
157
179
  }
158
180
  else
159
181
  {
@@ -175,4 +197,4 @@ module.exports = function(RED)
175
197
  }
176
198
 
177
199
  RED.nodes.registerType("hue-motion", HueMotion);
178
- }
200
+ }