node-red-contrib-huemagic 3.0.0 → 4.0.3

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 +631 -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 +111 -55
  29. package/huemagic/hue-buttons.html +197 -0
  30. package/huemagic/hue-buttons.js +158 -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 +105 -101
  39. package/huemagic/hue-rules.html +121 -50
  40. package/huemagic/hue-rules.js +89 -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 +120 -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
@@ -5,13 +5,12 @@ module.exports = function(RED)
5
5
  function HueMotion(config)
6
6
  {
7
7
  RED.nodes.createNode(this, config);
8
- var scope = this;
9
- let bridge = RED.nodes.getNode(config.bridge);
10
- let { HueMotionMessage } = require('../utils/messages');
11
- var universalMode = false;
12
8
 
13
- // SAVE LAST STATE
14
- var lastState = false;
9
+ const scope = this;
10
+ const bridge = RED.nodes.getNode(config.bridge);
11
+
12
+ // SAVE LAST COMMAND
13
+ this.lastCommand = null;
15
14
 
16
15
  //
17
16
  // CHECK CONFIG
@@ -25,7 +24,6 @@ module.exports = function(RED)
25
24
  // UNIVERSAL MODE?
26
25
  if(!config.sensorid)
27
26
  {
28
- universalMode = true;
29
27
  this.status({fill: "grey", shape: "dot", text: "hue-motion.node.universal"});
30
28
  }
31
29
 
@@ -37,131 +35,137 @@ module.exports = function(RED)
37
35
  }
38
36
 
39
37
  //
40
- // ON UPDATE
41
- if(config.sensorid) { bridge.events.on('sensor' + config.sensorid, function(sensor) { scope.receivedUpdates(sensor) }); }
42
- if(!config.sensorid && config.universalevents && config.universalevents == true) { bridge.events.on('sensor', function(sensor) { scope.receivedUpdates(sensor) }); }
43
-
44
- //
45
- // RECEIVED UPDATES
46
- this.receivedUpdates = function(sensor)
38
+ // SUBSCRIBE TO UPDATES FROM THE BRIDGE
39
+ bridge.subscribe("motion", config.sensorid, function(info)
47
40
  {
48
- if(sensor.config.reachable == false)
41
+ let currentState = bridge.get("motion", info.id);
42
+
43
+ // RESOURCE FOUND?
44
+ if(currentState !== false)
49
45
  {
50
- // SEND STATUS
51
- if(universalMode == false)
46
+ // SEND MESSAGE
47
+ if(!config.skipevents && (config.initevents || info.suppressMessage == false))
52
48
  {
53
- scope.status({fill: "red", shape: "ring", text: "hue-motion.node.not-reachable"});
49
+ // SET LAST COMMAND
50
+ if(scope.lastCommand !== null)
51
+ {
52
+ currentState.command = scope.lastCommand;
53
+ }
54
+
55
+ // SEND STATE
56
+ scope.send(currentState);
57
+
58
+ // RESET LAST COMMAND
59
+ scope.lastCommand = null;
54
60
  }
55
- }
56
- else if(sensor.config.on == true)
57
- {
58
- // SEND STATUS
59
- if(universalMode == false)
61
+
62
+ // NOT IN UNIVERAL MODE? -> CHANGE UI STATES
63
+ if(config.sensorid)
60
64
  {
61
- if(sensor.state.presence)
65
+ if(currentState.payload.reachable == false)
62
66
  {
63
- scope.status({fill: "green", shape: "dot", text: "hue-motion.node.motion"});
67
+ scope.status({fill: "red", shape: "ring", text: "hue-motion.node.not-reachable"});
64
68
  }
65
- else
69
+ else if(currentState.payload.active == true)
66
70
  {
67
- scope.status({fill: "grey", shape: "dot", text: "hue-motion.node.activated"});
71
+ if(currentState.payload.motion)
72
+ {
73
+ scope.status({fill: "green", shape: "dot", text: "hue-motion.node.motion"});
74
+ }
75
+ else
76
+ {
77
+ scope.status({fill: "grey", shape: "dot", text: "hue-motion.node.activated"});
78
+ }
79
+ }
80
+ else if(currentState.payload.active == false)
81
+ {
82
+ scope.status({fill: "red", shape: "ring", text: "hue-motion.node.deactivated"});
68
83
  }
69
84
  }
70
-
71
- // SEND MESSAGE
72
- var hueMotion = new HueMotionMessage(sensor, true, (universalMode == false) ? lastState : false);
73
- if(!config.skipevents) { scope.send(hueMotion.msg); }
74
-
75
- // SAVE LAST STATE
76
- lastState = sensor;
77
- }
78
- else if(sensor.config.on == false)
79
- {
80
- // SEND STATUS
81
- if(universalMode == false)
82
- {
83
- scope.status({fill: "red", shape: "ring", text: "hue-motion.node.deactivated"});
84
- }
85
-
86
- // SEND MESSAGE
87
- var hueMotion = new HueMotionMessage(sensor, false, (universalMode == false) ? lastState : false);
88
- if(!config.skipevents) { scope.send(hueMotion.msg); }
89
-
90
- // SAVE LAST STATE
91
- lastState = sensor;
92
85
  }
93
- }
86
+ });
94
87
 
95
88
  //
96
- // DISABLE / ENABLE SENSOR
89
+ // CONTROL SENSOR
97
90
  this.on('input', function(msg, send, done)
98
91
  {
99
- // Node-RED < 1.0
92
+ // REDEFINE SEND AND DONE IF NOT AVAILABLE
100
93
  send = send || function() { scope.send.apply(scope,arguments); }
94
+ done = done || function() { scope.done.apply(scope,arguments); }
95
+
96
+ // SAVE LAST COMMAND
97
+ scope.lastCommand = RED.util.cloneMessage(msg);
98
+
99
+ // CREATE PATCH
100
+ let patchObject = {};
101
101
 
102
- // DEFINE SENSOR ID
103
- var tempSensorID = (msg.topic != null && isNaN(msg.topic) == false && msg.topic.length > 0) ? parseInt(msg.topic) : config.sensorid;
102
+ // DEFINE SENSOR ID & CURRENT STATE
103
+ const tempSensorID = (!config.sensorid && typeof msg.topic != 'undefined' && bridge.validResourceID.test(msg.topic) === true) ? msg.topic : config.sensorid;
104
+ if(!tempSensorID)
105
+ {
106
+ scope.error("Please submit a valid sensor ID.");
107
+ return false;
108
+ }
109
+
110
+ let currentState = bridge.get("motion", tempSensorID);
104
111
 
105
112
  // GET CURRENT STATE
106
- if(typeof msg.payload != 'undefined' && typeof msg.payload.status != 'undefined')
113
+ if( (typeof msg.payload != 'undefined' && typeof msg.payload.status != 'undefined') || (typeof msg.__user_inject_props__ != 'undefined' && msg.__user_inject_props__ == "status") )
107
114
  {
108
- bridge.client.sensors.getById(tempSensorID)
109
- .then(sensor => {
110
- var hueMotion = new HueMotionMessage(sensor, (sensor.config.on) ? true : false, (universalMode == false) ? lastState : false);
115
+ // SET LAST COMMAND
116
+ if(scope.lastCommand !== null)
117
+ {
118
+ currentState.command = scope.lastCommand;
119
+ }
111
120
 
112
- // SAVE LAST STATE
113
- lastState = sensor;
121
+ // SEND STATE
122
+ scope.send(currentState);
114
123
 
115
- return send(hueMotion.msg);
116
- });
124
+ // RESET LAST COMMAND
125
+ scope.lastCommand = null;
117
126
 
127
+ if(done) { done(); }
118
128
  return true;
119
129
  }
120
130
 
121
- // CONTROL
122
- if(msg.payload == true || msg.payload == false)
131
+ // TURN ON / OFF
132
+ if((msg.payload === true || msg.payload === false) && (msg.payload != currentState.payload.active))
123
133
  {
124
- bridge.client.sensors.getById(tempSensorID)
125
- .then(sensor => {
126
- sensor.config.on = msg.payload;
127
- return bridge.client.sensors.save(sensor);
128
- })
129
- .then(sensor => {
130
- var hueMotion = new HueMotionMessage(sensor, msg.payload, lastState);
131
-
132
- // SEND STATUS
133
- if(universalMode == false)
134
- {
135
- if(msg.payload == false)
136
- {
137
- scope.status({fill: "red", shape: "ring", text: "hue-motion.node.deactivated"});
138
- }
139
- else
140
- {
141
- scope.status({fill: "green", shape: "dot", text: "hue-motion.node.activated"});
142
- }
143
- }
134
+ // PREPARE PATCH
135
+ patchObject["enabled"] = (msg.payload == true);
136
+ }
144
137
 
145
- // SEND MESSAGE
146
- if(!config.skipevents) { send(hueMotion.msg); }
147
- if(done) { done(); }
148
-
149
- // SAVE LAST STATE
150
- lastState = sensor;
151
- })
152
- .catch(error => {
153
- scope.error(error, msg);
154
- if(done) { done(error); }
155
- });
138
+ //
139
+ // SHOULD PATCH?
140
+ if(Object.values(patchObject).length > 0)
141
+ {
142
+ // CHANGE NODE UI STATE
143
+ if(config.sensorid)
144
+ {
145
+ scope.status({fill: "grey", shape: "ring", text: "hue-motion.node.command"});
146
+ }
147
+
148
+ // PATCH!
149
+ bridge.patch("motion", tempSensorID, patchObject)
150
+ .then(function() { if(done) { done(); }})
151
+ .catch(function(errors) { scope.error(errors); });
156
152
  }
157
- });
153
+ else
154
+ {
155
+ // SET LAST COMMAND
156
+ if(scope.lastCommand !== null)
157
+ {
158
+ currentState.command = scope.lastCommand;
159
+ }
158
160
 
161
+ // SEND STATE
162
+ scope.send(currentState);
159
163
 
160
- //
161
- // CLOSE NODE / REMOVE EVENT LISTENER
162
- this.on('close', function()
163
- {
164
- bridge.events.removeAllListeners('sensor' + config.sensorid);
164
+ // RESET LAST COMMAND
165
+ scope.lastCommand = null;
166
+
167
+ if(done) { done(); }
168
+ }
165
169
  });
166
170
  }
167
171
 
@@ -1,27 +1,34 @@
1
1
  <script type="text/x-red" data-template-name="hue-rules">
2
2
  <div class="form-row">
3
3
  <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="hue-rules.config.name"></span></label>
4
- <input type="text" id="node-input-name" data-i18n="[placeholder]hue-rules.config.input-name">
4
+ <input type="text" id="node-input-name" data-i18n="[placeholder]hue-rules.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-ruleid"><i class="fa fa-tasks"></i> <span data-i18n="hue-rules.config.rule"></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-ruleid" 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-ruleid" placeholder="0" style="width: 100%"/>
15
15
  </div>
16
- <a id="node-config-input-scan-rules" class="editor-button" style="position: absolute; right: 0px; top: 0px;">
16
+ <button id="node-config-input-scan-rules" type="button" class="red-ui-button" style="margin-left: 10px;">
17
17
  <i class="fa fa-search"></i>
18
- </a>
18
+ </button>
19
+ </div>
20
+ </div>
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-rules.config.skipevents-node" style="width: 100%; margin-left: 10px;"></span>
19
25
  </div>
20
26
  </div>
21
27
  <div class="form-row">
22
- <label for="node-input-skipevents"><i class="fa fa-sign-out"></i> <span data-i18n="hue-rules.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-rules.config.skipevents-node"></span>
24
- </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-rules.config.sendinitevents-node" style="width: 100%; margin-left: 10px;"></span>
31
+ </div>
25
32
  </div>
26
33
  </script>
27
34
 
@@ -30,90 +37,154 @@
30
37
  category: 'HueMagic',
31
38
  color: '#bddb37',
32
39
  defaults: {
33
- name: {value:""},
34
- bridge: {type: "hue-bridge", required: true},
35
- ruleid: {value:"", required: true, validate: RED.validators.number()},
36
- skipevents: {value: false}
40
+ name: { value:"" },
41
+ bridge: { type: "hue-bridge", required: true },
42
+ ruleid: { value:"", required: false },
43
+ skipevents: { value: false },
44
+ initevents: { value: false }
37
45
  },
46
+ align: 'left',
47
+ icon: "hue-rules.png",
38
48
  inputs: 1,
39
49
  outputs: 1,
50
+ label: function() {
51
+ return this.name || this._("hue-rules.node.title");
52
+ },
53
+ paletteLabel: function() {
54
+ return this._("hue-rules.node.title");
55
+ },
40
56
  inputLabels: function() {
41
57
  return this._("hue-rules.node.input");
42
58
  },
43
59
  outputLabels: function() {
44
60
  return this._("hue-rules.node.output");
45
61
  },
46
- align: 'right',
47
- icon: "hue-rules.png",
48
- paletteLabel: function() {
49
- return this._("hue-rules.node.title");
50
- },
51
- label: function() {
52
- return this.name || this._("hue-rules.node.title");
53
- },
54
62
  oneditprepare: function()
55
63
  {
56
- var scope = this;
64
+ const scope = this;
65
+ let options = [];
57
66
 
58
- function manualRuleID()
67
+ function manualInput()
59
68
  {
69
+ // GET CURRENT SELECTED VALUE
60
70
  var current = $('#node-input-ruleid').val();
61
- $('#node-input-ruleid').replaceWith('<input type="text" id="node-input-ruleid" style="width: 100%"/>');
62
- $('#node-input-ruleid').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-ruleid" placeholder="0" style="width: 100%" value="'+current+'" />');
77
+
78
+ // CHANGE BUTTON ICON
79
+ var button = $("#node-config-input-scan-rules");
80
+ var buttonIcon = button.find("i");
81
+ buttonIcon.removeClass("fa-pencil");
82
+ buttonIcon.addClass("fa-search");
63
83
  }
64
84
 
65
- function searchAndSelectRuleID()
85
+ function searchAndSelect()
66
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
67
92
  var current = $('#node-input-ruleid').val();
68
- $('#node-input-ruleid').replaceWith('<select id="node-input-ruleid" style="width: 100%"></select>');
69
- $('#node-input-ruleid').append('<option selected="selected" value="null">'+scope._("hue-rules.config.searching")+'</option>');
70
93
 
71
- var bridgeConfig = RED.nodes.node($('#node-input-bridge option:selected').val());
72
- $.get('hue/rules', {bridge: bridgeConfig.bridge, key: bridgeConfig.key})
73
- .done( function(data) {
74
- var rules = JSON.parse(data);
94
+ // TRIGGER SEARCHING NOTIFICATION
95
+ var notification = RED.notify(scope._("hue-rules.config.searching"), { type: "compact", modal: true, fixed: true });
75
96
 
76
- if(rules.length <= 0)
97
+ // GET THE SENSORS
98
+ $.get('hue/resources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "rule" })
99
+ .done( function(data) {
100
+ var allResources = JSON.parse(data);
101
+ if(allResources.length <= 0)
77
102
  {
78
- RED.notify(scope._("hue-rules.config.none-found"), "error");
103
+ notification.close();
104
+ RED.notify(scope._("hue-rules.config.none-found"), { type: "error" });
105
+ return false;
79
106
  }
80
107
 
81
- // RESET OPTIONS
82
- $('#node-input-ruleid').empty();
83
-
84
- // SET TEMPERATURE SENSORS AS OPTIONS
85
- rules.forEach(function(rule)
108
+ // SET OPTIONS
109
+ allResources.forEach(function(resource)
86
110
  {
87
- $('#node-input-ruleid').append('<option value="' + rule.id + '">' + rule.name + '</option>');
111
+ options[resource.id] = { value: resource.id, label: resource.name };
88
112
  });
89
113
 
90
114
  // SELECT CURRENT VALUE
91
- $('#node-input-ruleid').val(current);
115
+ $("#node-input-ruleid").typedInput({
116
+ types: [
117
+ {
118
+ value: current,
119
+ options: Object.values(options)
120
+ }
121
+ ]
122
+ });
123
+
124
+ // CHANGE BUTTON ICON
125
+ var button = $("#node-config-input-scan-rules");
126
+ var buttonIcon = button.find("i");
127
+ buttonIcon.removeClass("fa-search");
128
+ buttonIcon.addClass("fa-pencil");
129
+
130
+ // CLOSE SEARCH NOTIFICATION
131
+ notification.close();
92
132
  })
93
133
  .fail(function()
94
134
  {
135
+ notification.close();
95
136
  RED.notify(scope._("hue-rules.config.unknown-error"), "error");
96
137
  });
97
138
  }
98
139
 
99
- $(document).on('change', '#node-input-ruleid', function()
140
+ // CHANGED RULE ID? -> REPLACE NAME (IF POSSIBLE)
141
+ $(document).on('change', '#node-input-ruleid', function(e)
100
142
  {
101
- var sensorName = $('#node-input-ruleid option:selected').text();
102
- if(sensorName.length > 0)
143
+ let currentSelectedOptionID = $(e.currentTarget).val();
144
+ let currentSelectedOptionValue = (currentSelectedOptionID.length > 0 && options[currentSelectedOptionID]) ? options[currentSelectedOptionID].label : false;
145
+
146
+ if(currentSelectedOptionValue !== false)
103
147
  {
104
- $('#node-input-name').val(sensorName);
148
+ $('#node-input-name').val(currentSelectedOptionValue.split(" (")[0]);
105
149
  }
106
150
  });
107
151
 
152
+ // TOGGLE SELECT/INPUT FIELD
108
153
  $('#node-config-input-scan-rules').click(function()
109
154
  {
110
- if($('#node-input-ruleid').prop("tagName") === "INPUT")
155
+ if($('#input-select-toggle').find(".red-ui-typedInput-container").length > 0)
156
+ {
157
+ manualInput();
158
+ }
159
+ else
111
160
  {
112
- searchAndSelectRuleID();
113
- } else {
114
- manualRuleID();
161
+ searchAndSelect();
115
162
  }
116
163
  });
164
+ },
165
+ button: {
166
+ enabled: function() {
167
+ return (this.ruleid && (this.ruleid == 0 || this.ruleid.length > 0 || this.ruleid > -1))
168
+ },
169
+ visible: function() {
170
+ return (this.ruleid && (this.ruleid == 0 || this.ruleid.length > 0 || this.ruleid > -1))
171
+ },
172
+ onclick: function()
173
+ {
174
+ const node = this;
175
+ if(node.bridge)
176
+ {
177
+ $.ajax({
178
+ url: "inject/" + node.id,
179
+ type: "POST",
180
+ data: JSON.stringify({ __user_inject_props__: "status"}),
181
+ contentType: "application/json; charset=utf-8",
182
+ success: function (resp) {
183
+ RED.notify(node.name + ": " + node._("hue-rules.node.statusmsg"), { type: "success", id: "status", timeout: 2000 });
184
+ }
185
+ });
186
+ }
187
+ }
117
188
  }
118
189
  });
119
190
  </script>