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.
Files changed (170) hide show
  1. package/CHANGELOG.md +229 -0
  2. package/README.md +807 -766
  3. package/examples/Hue Bridge.json +189 -35
  4. package/examples/Hue Brightness.json +124 -14
  5. package/examples/Hue Buttons.json +88 -0
  6. package/examples/Hue Group.json +575 -63
  7. package/examples/Hue Light.json +805 -58
  8. package/examples/Hue Magic.json +69 -24
  9. package/examples/Hue Motion.json +110 -42
  10. package/examples/Hue Rules.json +105 -37
  11. package/examples/Hue Scene.json +145 -28
  12. package/examples/Hue Temperature.json +124 -14
  13. package/huemagic/animations/001-sunny.json +22 -22
  14. package/huemagic/animations/002-cloudy.json +46 -46
  15. package/huemagic/animations/003-nightsky.json +20 -20
  16. package/huemagic/animations/004-sunrise.json +54 -54
  17. package/huemagic/animations/005-sunset.json +46 -46
  18. package/huemagic/animations/006-fireplace.json +74 -74
  19. package/huemagic/animations/007-spring.json +31 -31
  20. package/huemagic/animations/008-autmn.json +23 -23
  21. package/huemagic/animations/009-winter.json +23 -23
  22. package/huemagic/animations/010-dirtyfog.json +23 -23
  23. package/huemagic/animations/011-lgbt.json +49 -50
  24. package/huemagic/animations/012-rasta.json +28 -29
  25. package/huemagic/animations/013-strobo.json +30 -31
  26. package/huemagic/animations/014-randomrainbow.json +30 -31
  27. package/huemagic/animations/015-sos.json +158 -159
  28. package/huemagic/animations/016-milkyway.json +83 -0
  29. package/huemagic/animations/017-beach.json +40 -0
  30. package/huemagic/animations/018-forest.json +43 -0
  31. package/huemagic/animations/019-christmas.json +30 -0
  32. package/huemagic/animations/020-superhero.json +56 -0
  33. package/huemagic/animations/021-neoncity.json +52 -0
  34. package/huemagic/animations/previews/001-sunny.gif +0 -0
  35. package/huemagic/animations/previews/002-cloudy.gif +0 -0
  36. package/huemagic/animations/previews/003-nightsky.gif +0 -0
  37. package/huemagic/animations/previews/004-sunrise.gif +0 -0
  38. package/huemagic/animations/previews/005-sunset.gif +0 -0
  39. package/huemagic/animations/previews/006-fireplace.gif +0 -0
  40. package/huemagic/animations/previews/007-spring.gif +0 -0
  41. package/huemagic/animations/previews/008-autmn.gif +0 -0
  42. package/huemagic/animations/previews/009-winter.gif +0 -0
  43. package/huemagic/animations/previews/010-dirtyfog.gif +0 -0
  44. package/huemagic/animations/previews/011-lgbt.gif +0 -0
  45. package/huemagic/animations/previews/012-rasta.gif +0 -0
  46. package/huemagic/animations/previews/013-strobo.gif +0 -0
  47. package/huemagic/animations/previews/014-randomrainbow.gif +0 -0
  48. package/huemagic/animations/previews/015-sos.gif +0 -0
  49. package/huemagic/animations/previews/016-milkyway.gif +0 -0
  50. package/huemagic/animations/previews/017-beach.gif +0 -0
  51. package/huemagic/animations/previews/018-forest.gif +0 -0
  52. package/huemagic/animations/previews/019-christmas.gif +0 -0
  53. package/huemagic/animations/previews/020-superhero.gif +0 -0
  54. package/huemagic/animations/previews/021-neoncity.gif +0 -0
  55. package/huemagic/hue-bridge-config.html +105 -61
  56. package/huemagic/hue-bridge-config.js +629 -320
  57. package/huemagic/hue-bridge.html +41 -21
  58. package/huemagic/hue-bridge.js +191 -398
  59. package/huemagic/hue-brightness.html +130 -49
  60. package/huemagic/hue-brightness.js +131 -35
  61. package/huemagic/hue-buttons.html +197 -0
  62. package/huemagic/hue-buttons.js +152 -0
  63. package/huemagic/hue-group.html +137 -60
  64. package/huemagic/hue-group.js +394 -368
  65. package/huemagic/hue-light.html +133 -59
  66. package/huemagic/hue-light.js +551 -337
  67. package/huemagic/hue-magic.html +91 -240
  68. package/huemagic/hue-magic.js +57 -27
  69. package/huemagic/hue-motion.html +128 -50
  70. package/huemagic/hue-motion.js +116 -87
  71. package/huemagic/hue-rules.html +121 -50
  72. package/huemagic/hue-rules.js +84 -64
  73. package/huemagic/hue-scene.html +96 -115
  74. package/huemagic/hue-scene.js +65 -96
  75. package/huemagic/hue-temperature.html +130 -49
  76. package/huemagic/hue-temperature.js +136 -32
  77. package/huemagic/icons/hue-bridge.png +0 -0
  78. package/huemagic/icons/hue-bridge.svg +3 -0
  79. package/huemagic/icons/hue-brightness.png +0 -0
  80. package/huemagic/icons/hue-brightness.svg +11 -0
  81. package/huemagic/icons/hue-buttons.png +0 -0
  82. package/huemagic/icons/hue-buttons.svg +4 -0
  83. package/huemagic/icons/hue-group.png +0 -0
  84. package/huemagic/icons/hue-group.svg +12 -0
  85. package/huemagic/icons/hue-light.png +0 -0
  86. package/huemagic/icons/hue-light.svg +3 -0
  87. package/huemagic/icons/hue-magic.png +0 -0
  88. package/huemagic/icons/hue-magic.svg +3 -0
  89. package/huemagic/icons/hue-motion.png +0 -0
  90. package/huemagic/icons/hue-motion.svg +9 -0
  91. package/huemagic/icons/hue-rules.png +0 -0
  92. package/huemagic/icons/hue-rules.svg +4 -0
  93. package/huemagic/icons/hue-scene.png +0 -0
  94. package/huemagic/icons/hue-scene.svg +5 -0
  95. package/huemagic/icons/hue-temperature.png +0 -0
  96. package/huemagic/icons/hue-temperature.svg +7 -0
  97. package/huemagic/locales/de/hue-bridge-config.html +17 -12
  98. package/huemagic/locales/de/hue-bridge-config.json +7 -5
  99. package/huemagic/locales/de/hue-bridge.html +64 -145
  100. package/huemagic/locales/de/hue-bridge.json +6 -17
  101. package/huemagic/locales/de/hue-brightness.html +52 -38
  102. package/huemagic/locales/de/hue-brightness.json +7 -2
  103. package/huemagic/locales/de/hue-buttons.html +58 -0
  104. package/huemagic/locales/de/{hue-button.json → hue-buttons.json} +8 -8
  105. package/huemagic/locales/de/hue-group.html +46 -122
  106. package/huemagic/locales/de/hue-group.json +4 -2
  107. package/huemagic/locales/de/hue-light.html +68 -116
  108. package/huemagic/locales/de/hue-light.json +5 -2
  109. package/huemagic/locales/de/hue-magic.html +65 -57
  110. package/huemagic/locales/de/hue-magic.json +2 -1
  111. package/huemagic/locales/de/hue-motion.html +48 -44
  112. package/huemagic/locales/de/hue-motion.json +6 -3
  113. package/huemagic/locales/de/hue-rules.html +68 -73
  114. package/huemagic/locales/de/hue-rules.json +5 -2
  115. package/huemagic/locales/de/hue-scene.html +23 -32
  116. package/huemagic/locales/de/hue-scene.json +5 -2
  117. package/huemagic/locales/de/hue-temperature.html +53 -36
  118. package/huemagic/locales/de/hue-temperature.json +7 -2
  119. package/huemagic/locales/en-US/hue-bridge-config.html +17 -12
  120. package/huemagic/locales/en-US/hue-bridge-config.json +5 -3
  121. package/huemagic/locales/en-US/hue-bridge.html +64 -145
  122. package/huemagic/locales/en-US/hue-bridge.json +5 -16
  123. package/huemagic/locales/en-US/hue-brightness.html +52 -38
  124. package/huemagic/locales/en-US/hue-brightness.json +10 -3
  125. package/huemagic/locales/en-US/hue-buttons.html +58 -0
  126. package/huemagic/locales/en-US/{hue-button.json → hue-buttons.json} +11 -5
  127. package/huemagic/locales/en-US/hue-group.html +46 -122
  128. package/huemagic/locales/en-US/hue-group.json +7 -3
  129. package/huemagic/locales/en-US/hue-light.html +68 -116
  130. package/huemagic/locales/en-US/hue-light.json +8 -3
  131. package/huemagic/locales/en-US/hue-magic.html +65 -57
  132. package/huemagic/locales/en-US/hue-magic.json +3 -1
  133. package/huemagic/locales/en-US/hue-motion.html +48 -44
  134. package/huemagic/locales/en-US/hue-motion.json +9 -4
  135. package/huemagic/locales/en-US/hue-rules.html +68 -73
  136. package/huemagic/locales/en-US/hue-rules.json +5 -2
  137. package/huemagic/locales/en-US/hue-scene.html +23 -32
  138. package/huemagic/locales/en-US/hue-scene.json +5 -2
  139. package/huemagic/locales/en-US/hue-temperature.html +53 -36
  140. package/huemagic/locales/en-US/hue-temperature.json +10 -3
  141. package/huemagic/utils/api.js +290 -0
  142. package/huemagic/utils/color.js +382 -0
  143. package/{utils → huemagic/utils}/merge.js +9 -6
  144. package/huemagic/utils/messages.js +447 -0
  145. package/package.json +11 -12
  146. package/examples/Hue Switch.json +0 -40
  147. package/examples/Hue Tap.json +0 -40
  148. package/huemagic/assets/anime.js +0 -8
  149. package/huemagic/hue-button.html +0 -119
  150. package/huemagic/hue-button.js +0 -94
  151. package/huemagic/hue-switch.html +0 -119
  152. package/huemagic/hue-switch.js +0 -113
  153. package/huemagic/hue-tap.html +0 -119
  154. package/huemagic/hue-tap.js +0 -74
  155. package/huemagic/icons/hue-button.png +0 -0
  156. package/huemagic/icons/hue-switch.png +0 -0
  157. package/huemagic/icons/hue-tap.png +0 -0
  158. package/huemagic/locales/de/hue-button.html +0 -50
  159. package/huemagic/locales/de/hue-switch.html +0 -50
  160. package/huemagic/locales/de/hue-switch.json +0 -31
  161. package/huemagic/locales/de/hue-tap.html +0 -41
  162. package/huemagic/locales/de/hue-tap.json +0 -23
  163. package/huemagic/locales/en-US/hue-button.html +0 -50
  164. package/huemagic/locales/en-US/hue-switch.html +0 -50
  165. package/huemagic/locales/en-US/hue-switch.json +0 -31
  166. package/huemagic/locales/en-US/hue-tap.html +0 -41
  167. package/huemagic/locales/en-US/hue-tap.json +0 -23
  168. package/utils/color.js +0 -9
  169. package/utils/messages.js +0 -658
  170. package/utils/rgb.js +0 -188
@@ -1,7 +1,7 @@
1
1
  <script type="text/x-red" data-template-name="hue-magic">
2
2
  <div class="form-row">
3
3
  <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="hue-magic.config.name"></span></label>
4
- <input type="text" id="node-input-name" data-i18n="[placeholder]hue-magic.config.input-name">
4
+ <input type="text" id="node-input-name" data-i18n="[placeholder]hue-magic.config.input-name" style="width: calc(100% - 105px)">
5
5
  </div>
6
6
  <div class="form-row">
7
7
  <label for="node-input-endless"><i class="fa fa-refresh"></i> <span data-i18n="hue-magic.config.loop"></span></label>
@@ -13,21 +13,20 @@
13
13
  <input type="checkbox" id="node-input-restore" style="display:inline-block; width:22px; vertical-align:baseline;"><span data-i18n="hue-magic.config.restore-state"></span>
14
14
  </label>
15
15
  </div>
16
- <div class="form-row">
16
+ <div class="form-row" style="margin-top: 30px">
17
17
  <label for="node-input-steps"><i class="fa fa-magic"></i> <span data-i18n="hue-magic.config.animation"></span></label>
18
18
  </div>
19
19
  <div style="display: none;">
20
20
  <div class="form-row">
21
- <input type="text" id="node-input-preset" placeholder="...">
21
+ <input type="text" id="node-input-preset" placeholder="{}">
22
22
  </div>
23
23
  <div class="form-row">
24
- <input type="text" id="node-input-steps" placeholder="...">
24
+ <input type="text" id="node-input-steps" placeholder="{}">
25
25
  </div>
26
26
  </div>
27
27
  <div class="form-row form-animations">
28
28
  <div class="animation template">
29
- <div class="color"></div>
30
- <div class="brightness"></div>
29
+ <img src="#" class="color">
31
30
  <div class="info">
32
31
  <span><name>Name</name> <dur>(dur)</dur></span>
33
32
  </div>
@@ -43,9 +42,10 @@
43
42
  display: grid;
44
43
  -ms-grid-columns: 30% 3.29% 30% 3.29% 30%;
45
44
  grid-template-columns: 30% 30% 30%;
46
- grid-gap: 3.29%;
45
+ grid-gap: 2.29% 3.29%;
47
46
 
48
47
  max-width: 40vw;
48
+ padding-bottom: 85px;
49
49
  }
50
50
 
51
51
  .form-animations .animation
@@ -53,12 +53,15 @@
53
53
  position: relative;
54
54
  cursor: pointer;
55
55
 
56
+ border-radius: 20px;
56
57
  overflow: hidden;
57
- -webkit-border-radius: 5px;
58
- -moz-border-radius: 5px;
59
- border-radius: 5px;
60
58
 
61
- border: 3px solid #fff;
59
+ border: 2px solid #fff;
60
+ -webkit-transition: -webkit-box-shadow 333ms ease-in-out;
61
+ transition: -webkit-box-shadow 333ms ease-in-out;
62
+ -o-transition: box-shadow 333ms ease-in-out;
63
+ transition: box-shadow 333ms ease-in-out;
64
+ transition: box-shadow 333ms ease-in-out, -webkit-box-shadow 333ms ease-in-out;
62
65
  }
63
66
 
64
67
  .form-animations .animation.template
@@ -66,25 +69,17 @@
66
69
  display: none;
67
70
  }
68
71
 
69
- .form-animations .animation.selected
72
+ .form-animations .animation:active
70
73
  {
71
- border: 3px solid #000;
74
+ opacity: 0.7;
72
75
  }
73
76
 
74
- .form-animations .animation .color
77
+ .form-animations .animation.selected
75
78
  {
76
- position: absolute;
77
-
78
- top: 0;
79
- left: 0;
80
-
81
- height: 100%;
82
- width: 100%;
83
-
84
- z-index: 1;
79
+ box-shadow: 0 10px 40px rgba(0,0,0,0.1), 0 6px 13px rgba(0,0,0,0.23);
85
80
  }
86
81
 
87
- .form-animations .animation .brightness
82
+ .form-animations .animation .color
88
83
  {
89
84
  position: absolute;
90
85
 
@@ -94,11 +89,8 @@
94
89
  height: 100%;
95
90
  width: 100%;
96
91
 
97
- z-index: 11;
98
- opacity: 0;
99
-
100
- background: rgb(0,0,0);
101
- background: linear-gradient(0deg, rgba(0,0,0,1) 0%, rgba(77,77,77,1) 100%);
92
+ z-index: 1;
93
+ pointer-events: none;
102
94
  }
103
95
 
104
96
  .form-animations .animation .info
@@ -116,17 +108,13 @@
116
108
 
117
109
  .form-animations .animation .info span
118
110
  {
119
- display: inline-block;
120
- margin: 0 auto;
121
-
111
+ display: block;
112
+ margin: 0 12px;
122
113
  color: #000;
123
114
  background-color: rgba(255,255,255,0.8);
124
115
  font-size: 11px;
125
- padding: 2.5px 5px;
126
-
127
- -webkit-border-radius: 3px;
128
- -moz-border-radius: 3px;
129
- border-radius: 3px;
116
+ padding: 2.5px 0;
117
+ border-radius: 8px;
130
118
  }
131
119
 
132
120
  .form-animations .animation .info span name
@@ -157,231 +145,77 @@
157
145
  category: 'HueMagic',
158
146
  color: '#ff4242',
159
147
  defaults: {
160
- name: {value:""},
161
- endless: {value: true},
162
- restore: {value: false},
163
- preset: {value: null},
164
- steps: {value: null}
148
+ name: { value:"" },
149
+ endless: { value: true },
150
+ restore: { value: false },
151
+ preset: { value: null },
152
+ steps: { value: null }
165
153
  },
154
+ align: 'left',
155
+ icon: "hue-magic.png",
166
156
  inputs: 1,
167
157
  outputs: 1,
158
+ label: function() {
159
+ return this.name || this._("hue-magic.node.title");
160
+ },
161
+ paletteLabel: function() {
162
+ return this._("hue-magic.node.title");
163
+ },
168
164
  inputLabels: function() {
169
165
  return this._("hue-magic.node.input");
170
166
  },
171
167
  outputLabels: function() {
172
168
  return this._("hue-magic.node.output");
173
169
  },
174
- align: 'right',
175
- icon: "hue-magic.png",
176
- paletteLabel: function() {
177
- return this._("hue-magic.node.title");
178
- },
179
- label: function() {
180
- return this.name || this._("hue-magic.node.title");
181
- },
182
170
  oneditprepare: function()
183
171
  {
184
- var scope = this;
172
+ const scope = this;
185
173
  this.animations = [];
186
174
 
187
175
  var preset = $('#node-input-preset').val();
188
- $.getScript("hue/assets/anime.js", function( data, textStatus, jqxhr )
176
+
177
+ // LOAD ANIMATIONS
178
+ $.get('hue/animations?nc=' + Math.random())
179
+ .done( function(data)
189
180
  {
190
- // LOAD ANIMATIONS
191
- $.get('hue/animations?nc=' + Math.random())
192
- .done( function(data)
181
+ scope.animations = JSON.parse(data);
182
+ $.each(scope.animations, function(i, animation)
193
183
  {
194
- // HELPER
195
- function rgbToHex(r, g, b)
196
- {
197
- return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
198
- }
199
-
200
- function adjustBrightness(hex, lum)
184
+ var animationTemplate = $(".animation.template").clone();
185
+ animationTemplate.removeClass("template");
186
+
187
+ // APPLY INFORMATION
188
+ animationTemplate.attr("data-id", animation.info.id);
189
+ animationTemplate.attr("data-name", animation.info.name);
190
+ animationTemplate.attr("data-steps", JSON.stringify(animation.steps));
191
+ animationTemplate.find("name").html(animation.info.name);
192
+ animationTemplate.find(".color").attr("src", "hue/animations/" + animation.info.id + ".gif");
193
+
194
+ // IS SELECTED?
195
+ if(preset == animation.info.id)
201
196
  {
202
- hex = String(hex).replace(/[^0-9a-f]/gi, '');
203
- if (hex.length < 6)
204
- {
205
- hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
206
- }
207
- lum = lum || 0;
208
-
209
- var rgb = "#", c, i;
210
- for (i = 0; i < 3; i++)
211
- {
212
- c = parseInt(hex.substr(i*2,2), 16);
213
- c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
214
- rgb += ("00"+c).substr(c.length);
215
- }
216
-
217
- return rgb;
197
+ animationTemplate.addClass("selected");
218
198
  }
219
199
 
220
- function randomHexColor() {
221
- return '#' + (Math.random() * 0xFFFFFF << 0).toString(16).padStart(6, "0");
222
- }
200
+ // CALC DURATION IN SECONDS AND ANIMATION
201
+ var duration = 0;
202
+ $.each(animation.steps, function(z, oneStep) { duration += oneStep.delay; });
223
203
 
224
- // FRAMES
225
- function addPreviewFrame(step)
226
- {
227
- // TRANSITION?
228
- var stepTransition = 300;
229
- if(typeof step.animation.transitionTime != 'undefined')
230
- {
231
- stepTransition = parseFloat(step.animation.transitionTime)*1000;
232
- }
204
+ // NORMALIZE DUR IN SECONDS
205
+ duration = duration/1000;
233
206
 
234
- // DEFINE COLOR
235
- var color = "#fff";
236
- if(typeof step.animation.rgb != 'undefined')
237
- {
238
- color = rgbToHex(step.animation.rgb[0], step.animation.rgb[1], step.animation.rgb[2]);
239
- }
240
- else if(typeof step.animation.hex != 'undefined')
241
- {
242
- color = step.animation.hex;
243
- }
244
- else if(typeof step.animation.color != 'undefined')
245
- {
246
- if(step.animation.color == "random"||step.animation.color == "any")
247
- {
248
- color = randomHexColor();
249
- }
250
- else
251
- {
252
- color = step.animation.color;
253
- }
254
- }
255
-
256
- // ADJUST COLOR BRIGHTNESS
257
- if(typeof step.animation.brightness != 'undefined')
258
- {
259
- var lum = (step.animation.brightness/100)-1;
260
- color = adjustBrightness(color, (lum < -0.5) ? -0.5 : lum);
261
- }
262
-
263
- return { background: color, delay: step.delay, duration: stepTransition };
264
- }
265
-
266
- function addPreviewFrameBrightness(step)
267
- {
268
- // TRANSITION?
269
- var stepTransition = 300;
270
- if(typeof step.animation.transitionTime != 'undefined')
271
- {
272
- stepTransition = parseFloat(step.animation.transitionTime)*1000;
273
- }
274
-
275
- // ADJUST COLOR BRIGHTNESS
276
- var opacity = 0;
277
- if(typeof step.animation.brightness != 'undefined')
278
- {
279
- opacity = 1-(step.animation.brightness/100);
280
- opacity = (opacity > 0.5) ? 0.5 : opacity;
281
- }
207
+ // HUMAN READABLE DURATION
208
+ var suffix = (duration <= 60) ? scope._("hue-magic.config.seconds") : scope._("hue-magic.config.minutes");
209
+ duration = (duration <= 60) ? (Math.round(duration * 10) / 10) : (Math.round( (duration/60) * 10 ) / 10);
210
+ animationTemplate.find("dur").html("("+duration + " " + suffix + ")");
282
211
 
283
- return { opacity: opacity, delay: step.delay, duration: stepTransition };
284
- }
285
-
286
- // LOGIC
287
- scope.animations = JSON.parse(data);
288
- $.each(scope.animations, function(i, animation)
289
- {
290
- var animationTemplate = $(".animation.template").clone();
291
- animationTemplate.removeClass("template");
292
-
293
- // APPLY INFORMATION
294
- animationTemplate.attr("data-id", animation.info.id);
295
- animationTemplate.attr("data-name", animation.info.name);
296
- animationTemplate.attr("data-steps", JSON.stringify(animation.steps));
297
- animationTemplate.find("name").html(animation.info.name);
298
-
299
- // SPECIAL CONFIGS?
300
- var randomOrder = false;
301
- if(typeof animation.specials != 'undefined')
302
- {
303
- // APPLY RANDOM ORDER CONFIG
304
- if(typeof animation.specials.randomOrder != 'undefined')
305
- {
306
- randomOrder = animation.specials.randomOrder;
307
- }
308
- }
309
-
310
- // IS SELECTED?
311
- if(preset == animation.info.id)
312
- {
313
- animationTemplate.addClass("selected");
314
- }
315
-
316
- // CALC DURATION IN SECONDS AND ANIMATION
317
- var duration = 0;
318
- var isFirst = true;
319
- var keyframes = [];
320
- // var keyframesBrightness = [];
321
- $.each(animation.steps, function(z, oneStep)
322
- {
323
- duration += oneStep.delay;
324
-
325
- // TRANSITION?
326
- if(typeof oneStep.animation.transitionTime != 'undefined')
327
- {
328
- duration += parseFloat(oneStep.animation.transitionTime)*1000;
329
- }
330
-
331
- if(isFirst == true)
332
- {
333
- oneStep.animation.transitionTime = 0;
334
- isFirst = false;
335
- }
336
-
337
- // SET CURRENT STEP COLOR
338
- keyframes.push(addPreviewFrame(oneStep));
339
- // keyframesBrightness.push(addPreviewFrameBrightness(oneStep));
340
- });
341
-
342
- // REPEAT KEYFRAMES FOR SMOOTH TRANSITIONS
343
- var r = 0;
344
- while (r < 10)
345
- {
346
- keyframes = keyframes.concat(keyframes);
347
- // keyframesBrightness = keyframesBrightness.concat(keyframesBrightness);
348
- r++;
349
- }
350
-
351
- // INITIALIZE COLOR ANIMATION
352
- var animationColorPreview = anime({
353
- targets: animationTemplate.find("div.color")[0],
354
- loop: true,
355
- autoplay: true,
356
- easing: 'linear',
357
- keyframes: keyframes
358
- });
359
-
360
- // INITIALIZE BRIGHTNESS ANIMATION
361
- // var animationBrightness = anime({
362
- // targets: animationTemplate.find("div.brightness")[0],
363
- // loop: true,
364
- // autoplay: true,
365
- // easing: 'linear',
366
- // keyframes: keyframesBrightness
367
- // });
368
-
369
- // NORMALIZE DUR IN SECONDS
370
- duration = duration/1000;
371
-
372
- // HUMAN READABLE DURATION
373
- var suffix = (duration <= 60) ? scope._("hue-magic.config.seconds") : scope._("hue-magic.config.minutes");
374
- duration = (duration <= 60) ? (Math.round(duration * 10) / 10) : (Math.round( (duration/60) * 10 ) / 10);
375
- animationTemplate.find("dur").html("("+duration + " " + suffix + ")");
376
-
377
- // PUSH TO FRONTEND
378
- animationTemplate.appendTo(".form-animations");
379
- });
380
- })
381
- .fail(function()
382
- {
383
- RED.notify(scope._("hue-magic.config.unknown-error"), "error");
212
+ // PUSH TO FRONTEND
213
+ animationTemplate.appendTo(".form-animations");
384
214
  });
215
+ })
216
+ .fail(function()
217
+ {
218
+ RED.notify(scope._("hue-magic.config.unknown-error"), "error");
385
219
  });
386
220
 
387
221
  // SELECT ANIMATION
@@ -403,9 +237,26 @@
403
237
  // SET STEPS
404
238
  var index = selectedAnimation.attr("data-id");
405
239
  var steps = JSON.stringify(JSON.parse(selectedAnimation.attr("data-steps")));
406
-
407
240
  $('#node-input-steps').val(steps);
408
241
  });
242
+ },
243
+ button: {
244
+ onclick: function()
245
+ {
246
+ const node = this;
247
+ if(node.steps)
248
+ {
249
+ $.ajax({
250
+ url: "inject/" + node.id,
251
+ type: "POST",
252
+ data: JSON.stringify({ __user_inject_props__: "play"}),
253
+ contentType: "application/json; charset=utf-8",
254
+ success: function (resp) {
255
+ RED.notify(node.name + ": " + node._("hue-magic.node.playmsg"), { type: "success", id: "status", timeout: 2000 });
256
+ }
257
+ });
258
+ }
259
+ }
409
260
  }
410
261
  });
411
262
  </script>
@@ -6,10 +6,10 @@ module.exports = function(RED)
6
6
  {
7
7
  RED.nodes.createNode(this, config);
8
8
 
9
- var scope = this;
10
- let async = require('async');
11
- var isEndless = config.endless;
12
- var restoreState = config.restore;
9
+ const scope = this;
10
+ const async = require('async');
11
+ const isEndless = config.endless;
12
+ const restoreState = config.restore;
13
13
 
14
14
  // STEPS INITIALIZATION
15
15
  this.steps = config.steps;
@@ -182,16 +182,25 @@ module.exports = function(RED)
182
182
  }
183
183
 
184
184
  //
185
- // ENABLE HUE MAGIC ANIMATION
185
+ // START THE HUEMAGIC ANIMATION
186
186
  this.on('input', function(msg, send, done)
187
187
  {
188
- // Node-RED < 1.0
188
+ // REDEFINE SEND AND DONE IF NOT AVAILABLE
189
189
  send = send || function() { scope.send.apply(scope,arguments); }
190
+ done = done || function() { scope.done.apply(scope,arguments); }
191
+
192
+ if(typeof msg.payload != 'undefined' && typeof msg.payload.steps != 'undefined')
193
+ {
194
+ scope.steps = msg.payload.steps;
195
+ msg.payload.animate = true;
196
+ }
197
+
198
+ const playFromButton = (typeof msg.__user_inject_props__ != 'undefined' && msg.__user_inject_props__ == "play");
190
199
 
191
- if(scope.steps != null||typeof msg.payload.steps != 'undefined')
200
+ if(scope.steps != null)
192
201
  {
193
202
  // SPECIALS CONFIG
194
- if(typeof msg.payload.specials != 'undefined')
203
+ if(typeof msg.payload != 'undefined' && typeof msg.payload.specials != 'undefined')
195
204
  {
196
205
  // APPLY RANDOM ORDER CONFIG
197
206
  if(typeof msg.payload.specials.randomOrder != 'undefined')
@@ -201,11 +210,11 @@ module.exports = function(RED)
201
210
  }
202
211
 
203
212
  // TURN ON ANIMATION
204
- if(typeof msg.payload.animate == 'undefined'||msg.payload.animate == true||msg.payload === true)
213
+ if(typeof msg.payload != 'undefined' && msg.payload.animate == true||msg.payload === true||playFromButton === true)
205
214
  {
215
+ var animationSteps = typeof scope.steps === 'string' ? JSON.parse(scope.steps) : scope.steps;
206
216
  if(scope.isAnimating == false)
207
217
  {
208
- var animationSteps = (typeof msg.payload.steps != 'undefined') ? msg.payload.steps : JSON.parse(scope.steps);
209
218
  scope.status({fill: "green", shape: "dot", text: "hue-magic.node.animating"});
210
219
 
211
220
  scope.isAnimating = true;
@@ -214,7 +223,7 @@ module.exports = function(RED)
214
223
  }
215
224
 
216
225
  // TURN OFF ANIMATION
217
- if((typeof msg.payload.animate != 'undefined' && msg.payload.animate == false)||msg.payload === false)
226
+ if((typeof msg.payload != 'undefined' && typeof msg.payload.animate != 'undefined' && msg.payload.animate == false)||msg.payload === false)
218
227
  {
219
228
  scope.animationStopped(done);
220
229
  scope.isAnimating = false;
@@ -244,36 +253,57 @@ module.exports = function(RED)
244
253
  // GET ANIMATIONS
245
254
  RED.httpAdmin.get('/hue/animations', function(req, res, next)
246
255
  {
247
- let fs = require("fs");
248
- let path = require("path");
256
+ const fs = require("fs");
257
+ const path = require("path");
258
+ const dir = path.resolve(__dirname, 'animations');
249
259
 
250
260
  var allAnimations = [];
251
- var dir = path.resolve(__dirname, 'animations');
261
+ fs.readdirSync(dir).forEach(function(filename)
262
+ {
263
+ try
264
+ {
265
+ var filepath = path.resolve(dir, filename);
266
+ var stat = fs.statSync(filepath);
267
+ var isFile = stat.isFile();
268
+ var fileID = path.basename(filepath, '.json');
252
269
 
253
- fs.readdirSync(dir).forEach(filename => {
254
- var filepath = path.resolve(dir, filename);
255
- var stat = fs.statSync(filepath);
256
- var isFile = stat.isFile();
257
- var fileID = path.basename(filepath, '.json');
270
+ if(isFile)
271
+ {
272
+ var animation = JSON.parse(fs.readFileSync(filepath, "utf8"));
273
+ animation.info.id = fileID;
258
274
 
259
- if(isFile)
275
+ allAnimations.push(animation);
276
+ };
277
+ }
278
+ catch(e)
260
279
  {
261
- var animation = JSON.parse(fs.readFileSync(filepath, "utf8"));
262
- animation.info.id = fileID;
263
-
264
- allAnimations.push(animation);
265
- };
280
+ console.log(fileID, e);
281
+ }
266
282
  });
267
283
 
268
284
  // SEND ALL ANIMATIONS
269
285
  res.end(JSON.stringify(allAnimations));
270
286
  });
271
287
 
288
+ //
289
+ // GET ANIMATION PREVIEWS
290
+ RED.httpAdmin.get('/hue/animations/:file', function(req, res, next)
291
+ {
292
+ let path = require("path");
293
+ res.sendFile(req.params.file, {
294
+ root: path.resolve(__dirname, 'animations', 'previews'),
295
+ dotfiles: 'deny'
296
+ });
297
+ });
298
+
272
299
  //
273
300
  // GET ASSETS
274
301
  RED.httpAdmin.get('/hue/assets/:file', function(req, res, next)
275
302
  {
276
303
  let path = require("path");
277
- res.sendFile(path.resolve(__dirname, 'assets', req.params.file));
304
+ res.sendFile(req.params.file, {
305
+ root: path.resolve(__dirname, 'assets'),
306
+ dotfiles: 'deny'
307
+ });
278
308
  });
279
- }
309
+ }