node-red-contrib-huemagic 3.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/README.md +764 -603
  2. package/examples/Hue Bridge.json +189 -35
  3. package/examples/Hue Brightness.json +124 -14
  4. package/examples/Hue Buttons.json +88 -0
  5. package/examples/Hue Group.json +575 -63
  6. package/examples/Hue Light.json +805 -58
  7. package/examples/Hue Magic.json +69 -24
  8. package/examples/Hue Motion.json +110 -42
  9. package/examples/Hue Rules.json +105 -37
  10. package/examples/Hue Scene.json +145 -28
  11. package/examples/Hue Temperature.json +124 -14
  12. package/huemagic/animations/019-christmas.json +30 -0
  13. package/huemagic/animations/020-superhero.json +56 -0
  14. package/huemagic/animations/021-neoncity.json +52 -0
  15. package/huemagic/animations/previews/006-fireplace.gif +0 -0
  16. package/huemagic/animations/previews/013-strobo.gif +0 -0
  17. package/huemagic/animations/previews/014-randomrainbow.gif +0 -0
  18. package/huemagic/animations/previews/016-milkyway.gif +0 -0
  19. package/huemagic/animations/previews/018-forest.gif +0 -0
  20. package/huemagic/animations/previews/019-christmas.gif +0 -0
  21. package/huemagic/animations/previews/020-superhero.gif +0 -0
  22. package/huemagic/animations/previews/021-neoncity.gif +0 -0
  23. package/huemagic/hue-bridge-config.html +105 -61
  24. package/huemagic/hue-bridge-config.js +628 -319
  25. package/huemagic/hue-bridge.html +41 -21
  26. package/huemagic/hue-bridge.js +190 -396
  27. package/huemagic/hue-brightness.html +127 -59
  28. package/huemagic/hue-brightness.js +105 -55
  29. package/huemagic/hue-buttons.html +197 -0
  30. package/huemagic/hue-buttons.js +152 -0
  31. package/huemagic/hue-group.html +137 -66
  32. package/huemagic/hue-group.js +387 -403
  33. package/huemagic/hue-light.html +132 -64
  34. package/huemagic/hue-light.js +544 -378
  35. package/huemagic/hue-magic.html +36 -20
  36. package/huemagic/hue-magic.js +49 -27
  37. package/huemagic/hue-motion.html +127 -59
  38. package/huemagic/hue-motion.js +99 -101
  39. package/huemagic/hue-rules.html +121 -50
  40. package/huemagic/hue-rules.js +83 -63
  41. package/huemagic/hue-scene.html +95 -114
  42. package/huemagic/hue-scene.js +64 -95
  43. package/huemagic/hue-temperature.html +127 -59
  44. package/huemagic/hue-temperature.js +114 -56
  45. package/huemagic/icons/hue-bridge.png +0 -0
  46. package/huemagic/icons/hue-bridge.svg +3 -0
  47. package/huemagic/icons/hue-brightness.png +0 -0
  48. package/huemagic/icons/hue-brightness.svg +11 -0
  49. package/huemagic/icons/hue-buttons.png +0 -0
  50. package/huemagic/icons/hue-buttons.svg +4 -0
  51. package/huemagic/icons/hue-group.png +0 -0
  52. package/huemagic/icons/hue-group.svg +12 -0
  53. package/huemagic/icons/hue-light.png +0 -0
  54. package/huemagic/icons/hue-light.svg +3 -0
  55. package/huemagic/icons/hue-magic.png +0 -0
  56. package/huemagic/icons/hue-magic.svg +3 -0
  57. package/huemagic/icons/hue-motion.png +0 -0
  58. package/huemagic/icons/hue-motion.svg +9 -0
  59. package/huemagic/icons/hue-rules.png +0 -0
  60. package/huemagic/icons/hue-rules.svg +4 -0
  61. package/huemagic/icons/hue-scene.png +0 -0
  62. package/huemagic/icons/hue-scene.svg +5 -0
  63. package/huemagic/icons/hue-temperature.png +0 -0
  64. package/huemagic/icons/hue-temperature.svg +7 -0
  65. package/huemagic/locales/de/hue-bridge-config.html +17 -12
  66. package/huemagic/locales/de/hue-bridge-config.json +7 -5
  67. package/huemagic/locales/de/hue-bridge.html +64 -145
  68. package/huemagic/locales/de/hue-bridge.json +6 -17
  69. package/huemagic/locales/de/hue-brightness.html +50 -50
  70. package/huemagic/locales/de/hue-brightness.json +6 -5
  71. package/huemagic/locales/de/hue-buttons.html +58 -0
  72. package/huemagic/locales/de/{hue-button.json → hue-buttons.json} +7 -11
  73. package/huemagic/locales/de/hue-group.html +46 -122
  74. package/huemagic/locales/de/hue-group.json +5 -5
  75. package/huemagic/locales/de/hue-light.html +68 -116
  76. package/huemagic/locales/de/hue-light.json +5 -5
  77. package/huemagic/locales/de/hue-magic.html +65 -57
  78. package/huemagic/locales/de/hue-magic.json +2 -1
  79. package/huemagic/locales/de/hue-motion.html +47 -50
  80. package/huemagic/locales/de/hue-motion.json +5 -5
  81. package/huemagic/locales/de/hue-rules.html +68 -73
  82. package/huemagic/locales/de/hue-rules.json +5 -2
  83. package/huemagic/locales/de/hue-scene.html +23 -32
  84. package/huemagic/locales/de/hue-scene.json +5 -2
  85. package/huemagic/locales/de/hue-temperature.html +51 -48
  86. package/huemagic/locales/de/hue-temperature.json +6 -5
  87. package/huemagic/locales/en-US/hue-bridge-config.html +17 -12
  88. package/huemagic/locales/en-US/hue-bridge-config.json +5 -3
  89. package/huemagic/locales/en-US/hue-bridge.html +64 -145
  90. package/huemagic/locales/en-US/hue-bridge.json +5 -16
  91. package/huemagic/locales/en-US/hue-brightness.html +50 -50
  92. package/huemagic/locales/en-US/hue-brightness.json +5 -2
  93. package/huemagic/locales/en-US/hue-buttons.html +58 -0
  94. package/huemagic/locales/en-US/{hue-button.json → hue-buttons.json} +6 -4
  95. package/huemagic/locales/en-US/hue-group.html +46 -122
  96. package/huemagic/locales/en-US/hue-group.json +4 -2
  97. package/huemagic/locales/en-US/hue-light.html +68 -116
  98. package/huemagic/locales/en-US/hue-light.json +4 -2
  99. package/huemagic/locales/en-US/hue-magic.html +65 -57
  100. package/huemagic/locales/en-US/hue-magic.json +3 -1
  101. package/huemagic/locales/en-US/hue-motion.html +47 -50
  102. package/huemagic/locales/en-US/hue-motion.json +4 -2
  103. package/huemagic/locales/en-US/hue-rules.html +68 -73
  104. package/huemagic/locales/en-US/hue-rules.json +5 -2
  105. package/huemagic/locales/en-US/hue-scene.html +23 -32
  106. package/huemagic/locales/en-US/hue-scene.json +5 -2
  107. package/huemagic/locales/en-US/hue-temperature.html +51 -48
  108. package/huemagic/locales/en-US/hue-temperature.json +5 -2
  109. package/huemagic/utils/api.js +290 -0
  110. package/huemagic/utils/color.js +382 -0
  111. package/{utils → huemagic/utils}/merge.js +4 -6
  112. package/huemagic/utils/messages.js +447 -0
  113. package/package.json +9 -15
  114. package/examples/Hue Button.json +0 -40
  115. package/examples/Hue Switch.json +0 -40
  116. package/examples/Hue Tap.json +0 -40
  117. package/huemagic/hue-button.html +0 -132
  118. package/huemagic/hue-button.js +0 -143
  119. package/huemagic/hue-switch.html +0 -132
  120. package/huemagic/hue-switch.js +0 -163
  121. package/huemagic/hue-tap.html +0 -132
  122. package/huemagic/hue-tap.js +0 -123
  123. package/huemagic/icons/hue-button.png +0 -0
  124. package/huemagic/icons/hue-switch.png +0 -0
  125. package/huemagic/icons/hue-tap.png +0 -0
  126. package/huemagic/locales/de/hue-button.html +0 -64
  127. package/huemagic/locales/de/hue-switch.html +0 -64
  128. package/huemagic/locales/de/hue-switch.json +0 -35
  129. package/huemagic/locales/de/hue-tap.html +0 -55
  130. package/huemagic/locales/de/hue-tap.json +0 -27
  131. package/huemagic/locales/en-US/hue-button.html +0 -64
  132. package/huemagic/locales/en-US/hue-switch.html +0 -64
  133. package/huemagic/locales/en-US/hue-switch.json +0 -35
  134. package/huemagic/locales/en-US/hue-tap.html +0 -55
  135. package/huemagic/locales/en-US/hue-tap.json +0 -27
  136. package/utils/color.js +0 -9
  137. package/utils/messages.js +0 -658
  138. 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,15 +13,15 @@
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">
@@ -145,31 +145,31 @@
145
145
  category: 'HueMagic',
146
146
  color: '#ff4242',
147
147
  defaults: {
148
- name: {value:""},
149
- endless: {value: true},
150
- restore: {value: false},
151
- preset: {value: null},
152
- steps: {value: null}
148
+ name: { value:"" },
149
+ endless: { value: true },
150
+ restore: { value: false },
151
+ preset: { value: null },
152
+ steps: { value: null }
153
153
  },
154
+ align: 'left',
155
+ icon: "hue-magic.png",
154
156
  inputs: 1,
155
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
+ },
156
164
  inputLabels: function() {
157
165
  return this._("hue-magic.node.input");
158
166
  },
159
167
  outputLabels: function() {
160
168
  return this._("hue-magic.node.output");
161
169
  },
162
- align: 'right',
163
- icon: "hue-magic.png",
164
- paletteLabel: function() {
165
- return this._("hue-magic.node.title");
166
- },
167
- label: function() {
168
- return this.name || this._("hue-magic.node.title");
169
- },
170
170
  oneditprepare: function()
171
171
  {
172
- var scope = this;
172
+ const scope = this;
173
173
  this.animations = [];
174
174
 
175
175
  var preset = $('#node-input-preset').val();
@@ -178,7 +178,6 @@
178
178
  $.get('hue/animations?nc=' + Math.random())
179
179
  .done( function(data)
180
180
  {
181
- // LOGIC
182
181
  scope.animations = JSON.parse(data);
183
182
  $.each(scope.animations, function(i, animation)
184
183
  {
@@ -238,9 +237,26 @@
238
237
  // SET STEPS
239
238
  var index = selectedAnimation.attr("data-id");
240
239
  var steps = JSON.stringify(JSON.parse(selectedAnimation.attr("data-steps")));
241
-
242
240
  $('#node-input-steps').val(steps);
243
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
+ }
244
260
  }
245
261
  });
246
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,25 +253,32 @@ 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
@@ -274,7 +290,10 @@ module.exports = function(RED)
274
290
  RED.httpAdmin.get('/hue/animations/:file', function(req, res, next)
275
291
  {
276
292
  let path = require("path");
277
- res.sendFile(path.resolve(__dirname, 'animations', 'previews', req.params.file));
293
+ res.sendFile(req.params.file, {
294
+ root: path.resolve(__dirname, 'animations', 'previews'),
295
+ dotfiles: 'deny'
296
+ });
278
297
  });
279
298
 
280
299
  //
@@ -282,6 +301,9 @@ module.exports = function(RED)
282
301
  RED.httpAdmin.get('/hue/assets/:file', function(req, res, next)
283
302
  {
284
303
  let path = require("path");
285
- 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
+ });
286
308
  });
287
309
  }
@@ -1,32 +1,34 @@
1
1
  <script type="text/x-red" data-template-name="hue-motion">
2
2
  <div class="form-row">
3
3
  <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="hue-motion.config.name"></span></label>
4
- <input type="text" id="node-input-name" data-i18n="[placeholder]hue-motion.config.input-name">
4
+ <input type="text" id="node-input-name" data-i18n="[placeholder]hue-motion.config.input-name" style="width: calc(100% - 105px)">
5
5
  </div>
6
6
  <div class="form-row">
7
7
  <label for="node-input-bridge"><i class="fa fa-server"></i> Bridge</label>
8
- <input type="text" id="node-input-bridge">
8
+ <input type="text" id="node-input-bridge" style="width: calc(100% - 105px)">
9
9
  </div>
10
10
  <div class="form-row">
11
11
  <label for="node-input-sensorid"><i class="fa fa-eye"></i> <span data-i18n="hue-motion.config.sensor"></span></label>
12
- <div style="display: inline-block; position: relative; width: 70%; height: 20px;">
13
- <div style="position: absolute; left: 0px; right: 40px;">
14
- <input type="text" id="node-input-sensorid" placeholder="1" style="width: 100%"/>
12
+ <div style="display: inline-flex; width: calc(100% - 105px)">
13
+ <div id="input-select-toggle" style="flex-grow: 1;">
14
+ <input type="text" id="node-input-sensorid" placeholder="00000000-0000-0000-0000-000000000000" style="width: 100%"/>
15
15
  </div>
16
- <a id="node-config-input-scan-sensors" class="editor-button" style="position: absolute; right: 0px; top: 0px;">
16
+ <button id="node-config-input-scan-sensors" type="button" class="red-ui-button" style="margin-left: 10px;">
17
17
  <i class="fa fa-search"></i>
18
- </a>
18
+ </button>
19
19
  </div>
20
20
  </div>
21
- <div class="form-row">
22
- <label for="node-input-skipevents"><i class="fa fa-sign-out"></i> <span data-i18n="hue-motion.config.skipevents"></span></label>
23
- <input type="checkbox" id="node-input-skipevents" style="display:inline-block; width:22px; vertical-align:baseline;"><span data-i18n="hue-motion.config.skipevents-node"></span>
24
- </label>
21
+ <div class="form-row" style="margin-top: 30px">
22
+ <div style="display: inline-flex; width: calc(100% - 105px)">
23
+ <input type="checkbox" id="node-input-skipevents" style="flex: 15px;">
24
+ <span data-i18n="hue-motion.config.skipevents-node" style="width: 100%; margin-left: 10px;"></span>
25
+ </div>
25
26
  </div>
26
27
  <div class="form-row">
27
- <label for="node-input-universalevents"><i class="fa fa-bullhorn"></i> <span data-i18n="hue-motion.config.universalevents"></span></label>
28
- <input type="checkbox" id="node-input-universalevents" style="display:inline-block; width:22px; vertical-align:baseline;"><span data-i18n="hue-motion.config.universalevents-node"></span>
29
- </label>
28
+ <div style="display: inline-flex; width: calc(100% - 105px)">
29
+ <input type="checkbox" id="node-input-initevents" style="flex: 15px;">
30
+ <span data-i18n="hue-motion.config.sendinitevents-node" style="width: 100%; margin-left: 10px;"></span>
31
+ </div>
30
32
  </div>
31
33
  </script>
32
34
 
@@ -35,95 +37,161 @@
35
37
  category: 'HueMagic',
36
38
  color: '#9876d3',
37
39
  defaults: {
38
- name: {value:""},
39
- bridge: {type: "hue-bridge", required: true},
40
- sensorid: {value:"", required: false, validate: function(id) {
41
- if(id.length < 1) { return true; }
42
- else if(!isNaN(id)) { return true; }
43
- else { return false; }
44
- }},
45
- skipevents: {value: false},
46
- universalevents: {value: false}
40
+ name: { value:"" },
41
+ bridge: { type: "hue-bridge", required: true },
42
+ sensorid: { value:"", required: false },
43
+ skipevents: { value: false },
44
+ initevents: { value: false }
47
45
  },
46
+ align: 'left',
47
+ icon: "hue-motion.png",
48
48
  inputs: 1,
49
49
  outputs: 1,
50
+ label: function() {
51
+ return this.name || this._("hue-motion.node.title");
52
+ },
53
+ paletteLabel: function() {
54
+ return this._("hue-motion.node.title");
55
+ },
50
56
  inputLabels: function() {
51
57
  return this._("hue-motion.node.input");
52
58
  },
53
59
  outputLabels: function() {
54
60
  return this._("hue-motion.node.output");
55
61
  },
56
- align: 'right',
57
- icon: "bridge.png",
58
- paletteLabel: function() {
59
- return this._("hue-motion.node.title");
60
- },
61
- label: function() {
62
- return this.name || this._("hue-motion.node.title");
63
- },
64
62
  oneditprepare: function()
65
63
  {
66
- var scope = this;
64
+ const scope = this;
65
+ let options = [];
67
66
 
68
- function manualMotionSensorID()
67
+ function manualInput()
69
68
  {
69
+ // GET CURRENT SELECTED VALUE
70
70
  var current = $('#node-input-sensorid').val();
71
- $('#node-input-sensorid').replaceWith('<input type="text" id="node-input-sensorid" style="width: 100%"/>');
72
- $('#node-input-sensorid').val(current);
71
+
72
+ // REMOVE SELECT FIELD
73
+ $('#input-select-toggle').empty();
74
+
75
+ // CREATE NEW INPUT FIELD
76
+ $('#input-select-toggle').append('<input type="text" id="node-input-sensorid" placeholder="00000000-0000-0000-0000-000000000000" style="width: 100%" value="'+current+'" />');
77
+
78
+ // CHANGE BUTTON ICON
79
+ var button = $("#node-config-input-scan-sensors");
80
+ var buttonIcon = button.find("i");
81
+ buttonIcon.removeClass("fa-pencil");
82
+ buttonIcon.addClass("fa-search");
73
83
  }
74
84
 
75
- function searchAndSelectMotionSensor()
85
+ function searchAndSelect()
76
86
  {
87
+ // GET CURRENT BRIDGE CONFIGURATION
88
+ var bridgeConfig = RED.nodes.node($('#node-input-bridge option:selected').val());
89
+ if(!bridgeConfig) { return false; }
90
+
91
+ // GET CURRENT SELECTED VALUE
77
92
  var current = $('#node-input-sensorid').val();
78
- $('#node-input-sensorid').replaceWith('<select id="node-input-sensorid" style="width: 100%"></select>');
79
- $('#node-input-sensorid').append('<option selected="selected" value="null">'+scope._("hue-motion.config.searching")+'</option>');
80
93
 
81
- var bridgeConfig = RED.nodes.node($('#node-input-bridge option:selected').val());
82
- $.get('hue/sensors', {bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "ZLLPresence"})
83
- .done(function(data) {
84
- var motionSensors = JSON.parse(data);
94
+ // TRIGGER SEARCHING NOTIFICATION
95
+ var notification = RED.notify(scope._("hue-motion.config.searching"), { type: "compact", modal: true, fixed: true });
85
96
 
86
- if(motionSensors.length <= 0)
97
+ // GET THE SENSORS
98
+ $.get('hue/ressources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "motion" })
99
+ .done( function(data) {
100
+ var allRessources = JSON.parse(data);
101
+ if(allRessources.length <= 0)
87
102
  {
88
- RED.notify(scope._("hue-motion.config.none-found"), "error");
103
+ notification.close();
104
+ RED.notify(scope._("hue-motion.config.none-found"), { type: "error" });
105
+ return false;
89
106
  }
90
107
 
91
- // RESET OPTIONS
92
- $('#node-input-sensorid').empty();
93
-
94
- // SET MOTION SENSORS AS OPTIONS
95
- motionSensors.forEach(function(sensor)
108
+ // SET OPTIONS
109
+ allRessources.forEach(function(ressource)
96
110
  {
97
- $('#node-input-sensorid').append('<option value="' + sensor.id + '">' + sensor.name + '</option>');
111
+ if(ressource.model)
112
+ {
113
+ options[ressource.id] = { value: ressource.id, label: ressource.name + " ("+ressource.model+")" };
114
+ }
115
+ else
116
+ {
117
+ options[ressource.id] = { value: ressource.id, label: ressource.name };
118
+ }
98
119
  });
99
120
 
100
121
  // SELECT CURRENT VALUE
101
- $('#node-input-sensorid').val(current);
122
+ $("#node-input-sensorid").typedInput({
123
+ types: [
124
+ {
125
+ value: current,
126
+ options: Object.values(options)
127
+ }
128
+ ]
129
+ });
130
+
131
+ // CHANGE BUTTON ICON
132
+ var button = $("#node-config-input-scan-sensors");
133
+ var buttonIcon = button.find("i");
134
+ buttonIcon.removeClass("fa-search");
135
+ buttonIcon.addClass("fa-pencil");
136
+
137
+ // CLOSE SEARCH NOTIFICATION
138
+ notification.close();
102
139
  })
103
140
  .fail(function()
104
141
  {
142
+ notification.close();
105
143
  RED.notify(scope._("hue-motion.config.unknown-error"), "error");
106
144
  });
107
145
  }
108
146
 
109
- $(document).on('change', '#node-input-sensorid', function()
147
+ // CHANGED SENSOR ID? -> REPLACE NAME (IF POSSIBLE)
148
+ $(document).on('change', '#node-input-sensorid', function(e)
110
149
  {
111
- var sensorName = $('#node-input-sensorid option:selected').text();
112
- if(sensorName.length > 0)
150
+ let currentSelectedOptionID = $(e.currentTarget).val();
151
+ let currentSelectedOptionValue = (currentSelectedOptionID.length > 0 && options[currentSelectedOptionID]) ? options[currentSelectedOptionID].label : false;
152
+
153
+ if(currentSelectedOptionValue !== false)
113
154
  {
114
- $('#node-input-name').val(sensorName);
155
+ $('#node-input-name').val(currentSelectedOptionValue.split(" (")[0]);
115
156
  }
116
157
  });
117
158
 
159
+ // TOGGLE SELECT/INPUT FIELD
118
160
  $('#node-config-input-scan-sensors').click(function()
119
161
  {
120
- if($('#node-input-sensorid').prop("tagName") === "INPUT")
162
+ if($('#input-select-toggle').find(".red-ui-typedInput-container").length > 0)
121
163
  {
122
- searchAndSelectMotionSensor();
123
- } else {
124
- manualMotionSensorID();
164
+ manualInput();
165
+ }
166
+ else
167
+ {
168
+ searchAndSelect();
125
169
  }
126
170
  });
171
+ },
172
+ button: {
173
+ enabled: function() {
174
+ return (this.sensorid && this.sensorid.length > 1)
175
+ },
176
+ visible: function() {
177
+ return (this.sensorid && this.sensorid.length > 1)
178
+ },
179
+ onclick: function()
180
+ {
181
+ const node = this;
182
+ if(node.bridge)
183
+ {
184
+ $.ajax({
185
+ url: "inject/" + node.id,
186
+ type: "POST",
187
+ data: JSON.stringify({ __user_inject_props__: "status"}),
188
+ contentType: "application/json; charset=utf-8",
189
+ success: function (resp) {
190
+ RED.notify(node.name + ": " + node._("hue-motion.node.statusmsg"), { type: "success", id: "status", timeout: 2000 });
191
+ }
192
+ });
193
+ }
194
+ }
127
195
  }
128
196
  });
129
197
  </script>