node-red-contrib-huemagic 4.0.2 → 4.1.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 (36) hide show
  1. package/README.md +31 -14
  2. package/examples/Hue Bridge.json +1 -1
  3. package/huemagic/hue-bridge-config.html +11 -4
  4. package/huemagic/hue-bridge-config.js +180 -154
  5. package/huemagic/hue-bridge.js +5 -5
  6. package/huemagic/hue-brightness.html +22 -8
  7. package/huemagic/hue-brightness.js +16 -5
  8. package/huemagic/hue-buttons.html +21 -7
  9. package/huemagic/hue-buttons.js +16 -5
  10. package/huemagic/hue-group.html +26 -12
  11. package/huemagic/hue-group.js +8 -3
  12. package/huemagic/hue-light.html +22 -8
  13. package/huemagic/hue-light.js +8 -3
  14. package/huemagic/hue-motion.html +22 -8
  15. package/huemagic/hue-motion.js +16 -5
  16. package/huemagic/hue-rules.html +20 -6
  17. package/huemagic/hue-rules.js +15 -4
  18. package/huemagic/hue-scene.html +20 -6
  19. package/huemagic/hue-scene.js +1 -1
  20. package/huemagic/hue-temperature.html +22 -8
  21. package/huemagic/hue-temperature.js +16 -5
  22. package/huemagic/locales/de/hue-bridge-config.html +8 -0
  23. package/huemagic/locales/de/hue-bridge.json +1 -1
  24. package/huemagic/locales/de/hue-group.html +1 -0
  25. package/huemagic/locales/en-US/hue-bridge-config.html +8 -0
  26. package/huemagic/locales/en-US/hue-bridge.html +1 -1
  27. package/huemagic/locales/en-US/hue-bridge.json +1 -1
  28. package/huemagic/locales/en-US/hue-buttons.html +1 -1
  29. package/huemagic/locales/en-US/hue-group.html +1 -0
  30. package/huemagic/locales/en-US/hue-light.html +1 -1
  31. package/huemagic/locales/en-US/hue-magic.html +3 -3
  32. package/huemagic/locales/en-US/hue-motion.html +1 -1
  33. package/huemagic/locales/en-US/hue-temperature.html +1 -1
  34. package/huemagic/utils/api.js +88 -94
  35. package/huemagic/utils/messages.js +134 -126
  36. package/package.json +2 -1
@@ -79,11 +79,11 @@ module.exports = function(RED)
79
79
 
80
80
  //
81
81
  // SUBSCRIBE TO UPDATES FROM THE BRIDGE
82
- bridge.subscribe("bridge", "globalRessourceUpdates", async function(info)
82
+ bridge.subscribe("bridge", "globalResourceUpdates", async function(info)
83
83
  {
84
84
  let currentState = bridge.get(info.updatedType, info.id);
85
85
 
86
- // RESSOURCE FOUND?
86
+ // RESOURCE FOUND?
87
87
  if(currentState !== false)
88
88
  {
89
89
  // UPDATE COUNTER
@@ -138,7 +138,7 @@ module.exports = function(RED)
138
138
  done = done || function() { scope.done.apply(scope,arguments); }
139
139
 
140
140
  // SET LAST COMMAND
141
- scope.lastCommand = msg;
141
+ scope.lastCommand = RED.util.cloneMessage(msg);
142
142
 
143
143
  // GET BRIDGE INFORMATION
144
144
  scope.getBridgeInformation()
@@ -171,7 +171,7 @@ module.exports = function(RED)
171
171
  if(done) { done(error); }
172
172
  });
173
173
  }
174
- // FETCH RESSOURCES
174
+ // FETCH RESOURCES
175
175
  else if(typeof msg.payload != 'undefined' && typeof msg.payload.fetch != 'undefined')
176
176
  {
177
177
  let fetchTypes = [];
@@ -179,7 +179,7 @@ module.exports = function(RED)
179
179
  else if(typeof msg.payload.fetch == 'object') { fetchTypes = msg.payload.fetch; }
180
180
  else { return false; }
181
181
 
182
- scope.status({fill: "blue", shape: "dot", text: "hue-bridge.node.f-ressources" });
182
+ scope.status({fill: "blue", shape: "dot", text: "hue-bridge.node.f-resources" });
183
183
 
184
184
  // FETCH
185
185
  bridgeInformation.results = {};
@@ -81,6 +81,19 @@
81
81
  buttonIcon.removeClass("fa-pencil");
82
82
  buttonIcon.addClass("fa-search");
83
83
  }
84
+
85
+ function sortResourcesBy(prop, resources)
86
+ {
87
+ return resources.sort((a, b) => {
88
+ if ( a[prop] < b[prop] ){
89
+ return -1;
90
+ }
91
+ if ( a[prop] > b[prop] ){
92
+ return 1;
93
+ }
94
+ return 0;
95
+ });
96
+ }
84
97
 
85
98
  function searchAndSelect()
86
99
  {
@@ -95,10 +108,11 @@
95
108
  var notification = RED.notify(scope._("hue-brightness.config.searching"), { type: "compact", modal: true, fixed: true });
96
109
 
97
110
  // GET THE SENSORS
98
- $.get('hue/ressources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "motion" })
111
+ $.get('hue/resources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "motion" })
99
112
  .done( function(data) {
100
- var allRessources = JSON.parse(data);
101
- if(allRessources.length <= 0)
113
+ var allResources = JSON.parse(data);
114
+ allResources = sortResourcesBy('name', allResources);
115
+ if(allResources.length <= 0)
102
116
  {
103
117
  notification.close();
104
118
  RED.notify(scope._("hue-brightness.config.none-found"), { type: "light_level" });
@@ -106,15 +120,15 @@
106
120
  }
107
121
 
108
122
  // SET OPTIONS
109
- allRessources.forEach(function(ressource)
123
+ allResources.forEach(function(resource)
110
124
  {
111
- if(ressource.model)
125
+ if(resource.model)
112
126
  {
113
- options[ressource.id] = { value: ressource.id, label: ressource.name + " ("+ressource.model+")" };
127
+ options[resource.id] = { value: resource.id, label: resource.name + " ("+resource.model+")" };
114
128
  }
115
129
  else
116
130
  {
117
- options[ressource.id] = { value: ressource.id, label: ressource.name };
131
+ options[resource.id] = { value: resource.id, label: resource.name };
118
132
  }
119
133
  });
120
134
 
@@ -194,4 +208,4 @@
194
208
  }
195
209
  }
196
210
  });
197
- </script>
211
+ </script>
@@ -40,7 +40,7 @@ module.exports = function(RED)
40
40
  {
41
41
  let currentState = bridge.get("light_level", info.id);
42
42
 
43
- // RESSOURCE FOUND?
43
+ // RESOURCE FOUND?
44
44
  if(currentState !== false)
45
45
  {
46
46
  // SEND MESSAGE
@@ -100,14 +100,25 @@ module.exports = function(RED)
100
100
  done = done || function() { scope.done.apply(scope,arguments); }
101
101
 
102
102
  // SET LAST COMMAND
103
- scope.lastCommand = msg;
103
+ scope.lastCommand = RED.util.cloneMessage(msg);
104
104
 
105
105
  // CREATE PATCH
106
106
  let patchObject = {};
107
107
 
108
108
  // DEFINE SENSOR ID & CURRENT STATE
109
- const tempSensorID = (typeof msg.topic != 'undefined' && msg.topic.length > 0) ? msg.topic : config.sensorid;
109
+ const tempSensorID = (!config.sensorid && typeof msg.topic != 'undefined' && bridge.validResourceID.test(msg.topic) === true) ? msg.topic : config.sensorid;
110
+ if(!tempSensorID)
111
+ {
112
+ scope.error("Please submit a valid sensor ID.");
113
+ return false;
114
+ }
115
+
110
116
  let currentState = bridge.get("light_level", tempSensorID);
117
+ if(!currentState)
118
+ {
119
+ 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..");
120
+ return false;
121
+ }
111
122
 
112
123
  // GET CURRENT STATE
113
124
  if( (typeof msg.payload != 'undefined' && typeof msg.payload.status != 'undefined') || (typeof msg.__user_inject_props__ != 'undefined' && msg.__user_inject_props__ == "status") )
@@ -129,10 +140,10 @@ module.exports = function(RED)
129
140
  }
130
141
 
131
142
  // TURN ON / OFF
132
- if((msg.payload === true || msg.payload === false) && (msg.payload !== currentState.payload.active))
143
+ if((msg.payload === true || msg.payload === false) && (msg.payload != currentState.payload.active))
133
144
  {
134
145
  // PREPARE PATCH
135
- patchObject.enabled = msg.payload;
146
+ patchObject["enabled"] = (msg.payload == true);
136
147
  }
137
148
 
138
149
  //
@@ -81,6 +81,19 @@
81
81
  buttonIcon.removeClass("fa-pencil");
82
82
  buttonIcon.addClass("fa-search");
83
83
  }
84
+
85
+ function sortResourcesBy(prop, resources)
86
+ {
87
+ return resources.sort((a, b) => {
88
+ if ( a[prop] < b[prop] ){
89
+ return -1;
90
+ }
91
+ if ( a[prop] > b[prop] ){
92
+ return 1;
93
+ }
94
+ return 0;
95
+ });
96
+ }
84
97
 
85
98
  function searchAndSelect()
86
99
  {
@@ -95,10 +108,11 @@
95
108
  var notification = RED.notify(scope._("hue-buttons.config.searching"), { type: "compact", modal: true, fixed: true });
96
109
 
97
110
  // GET THE SENSORS
98
- $.get('hue/ressources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "button" })
111
+ $.get('hue/resources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "button" })
99
112
  .done( function(data) {
100
- var allRessources = JSON.parse(data);
101
- if(allRessources.length <= 0)
113
+ var allResources = JSON.parse(data);
114
+ allResources = sortResourcesBy('name', allResources);
115
+ if(allResources.length <= 0)
102
116
  {
103
117
  notification.close();
104
118
  RED.notify(scope._("hue-buttons.config.none-found"), { type: "error" });
@@ -106,15 +120,15 @@
106
120
  }
107
121
 
108
122
  // SET OPTIONS
109
- allRessources.forEach(function(ressource)
123
+ allResources.forEach(function(resource)
110
124
  {
111
- if(ressource.model)
125
+ if(resource.model)
112
126
  {
113
- options[ressource.id] = { value: ressource.id, label: ressource.name + " ("+ressource.model+")" };
127
+ options[resource.id] = { value: resource.id, label: resource.name + " ("+resource.model+")" };
114
128
  }
115
129
  else
116
130
  {
117
- options[ressource.id] = { value: ressource.id, label: ressource.name };
131
+ options[resource.id] = { value: resource.id, label: resource.name };
118
132
  }
119
133
  });
120
134
 
@@ -43,7 +43,7 @@ module.exports = function(RED)
43
43
  {
44
44
  let currentState = bridge.get("button", info.id);
45
45
 
46
- // RESSOURCE FOUND?
46
+ // RESOURCE FOUND?
47
47
  if(currentState !== false)
48
48
  {
49
49
  // SEND MESSAGE
@@ -102,9 +102,9 @@ module.exports = function(RED)
102
102
  scope.status({fill: "grey", shape: "dot", text: "hue-buttons.node.waiting"});
103
103
 
104
104
  // REMOVE OLD BUTTON STATES
105
- for (const [oneButtonID, oneButton] of Object.entries(bridge.ressources[config.sensorid]["services"]["button"]))
105
+ for (const [oneButtonID, oneButton] of Object.entries(bridge.resources[config.sensorid]["services"]["button"]))
106
106
  {
107
- delete bridge.ressources[config.sensorid]["services"]["button"][oneButtonID]["button"];
107
+ delete bridge.resources[config.sensorid]["services"]["button"][oneButtonID]["button"];
108
108
  }
109
109
  }, 3000);
110
110
  }
@@ -121,11 +121,22 @@ module.exports = function(RED)
121
121
  done = done || function() { scope.done.apply(scope,arguments); }
122
122
 
123
123
  // SAVE LAST COMMAND
124
- scope.lastCommand = msg;
124
+ scope.lastCommand = RED.util.cloneMessage(msg);
125
125
 
126
126
  // DEFINE SENSOR ID
127
- const tempSensorID = (typeof msg.topic != 'undefined' && msg.topic.length > 0) ? msg.topic : config.sensorid;
127
+ const tempSensorID = (!config.sensorid && typeof msg.topic != 'undefined' && bridge.validResourceID.test(msg.topic) === true) ? msg.topic : config.sensorid;
128
+ if(!tempSensorID)
129
+ {
130
+ scope.error("Please submit a valid button ID.");
131
+ return false;
132
+ }
133
+
128
134
  let currentState = bridge.get("button", tempSensorID);
135
+ if(!currentState)
136
+ {
137
+ scope.error("The button/switch 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..");
138
+ return false;
139
+ }
129
140
 
130
141
  // GET CURRENT STATE
131
142
  if( (typeof msg.payload != 'undefined' && typeof msg.payload.status != 'undefined') || (typeof msg.__user_inject_props__ != 'undefined' && msg.__user_inject_props__ == "status") )
@@ -81,6 +81,19 @@
81
81
  buttonIcon.removeClass("fa-pencil");
82
82
  buttonIcon.addClass("fa-search");
83
83
  }
84
+
85
+ function sortResourcesBy(prop, resources)
86
+ {
87
+ return resources.sort((a, b) => {
88
+ if ( a[prop] < b[prop] ){
89
+ return -1;
90
+ }
91
+ if ( a[prop] > b[prop] ){
92
+ return 1;
93
+ }
94
+ return 0;
95
+ });
96
+ }
84
97
 
85
98
  function searchAndSelect()
86
99
  {
@@ -95,10 +108,11 @@
95
108
  var notification = RED.notify(scope._("hue-group.config.searching"), { type: "compact", modal: true, fixed: true });
96
109
 
97
110
  // GET THE GROUPS
98
- $.get('hue/ressources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "group" })
111
+ $.get('hue/resources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "group" })
99
112
  .done( function(data) {
100
- var allRessources = JSON.parse(data);
101
- if(allRessources.length <= 0)
113
+ var allResources = JSON.parse(data);
114
+ allResources = sortResourcesBy('name', allResources);
115
+ if(allResources.length <= 0)
102
116
  {
103
117
  notification.close();
104
118
  RED.notify(scope._("hue-group.config.none-found"), { type: "error" });
@@ -106,25 +120,25 @@
106
120
  }
107
121
 
108
122
  // SET GROUPS AS OPTIONS
109
- allRessources.forEach(function(ressource)
123
+ allResources.forEach(function(resource)
110
124
  {
111
- if(!ressource.name) // ALL SPECIAL
125
+ if(!resource.name) // ALL SPECIAL
112
126
  {
113
- options[ressource.id] = { value: ressource.id, label: "● "+scope._("hue-group.config.all") };
127
+ options[resource.id] = { value: resource.id, label: "● "+scope._("hue-group.config.all") };
114
128
  }
115
129
  });
116
130
 
117
- allRessources.forEach(function(ressource)
131
+ allResources.forEach(function(resource)
118
132
  {
119
- if(ressource.name) // REGULAR GROUPS
133
+ if(resource.name) // REGULAR GROUPS
120
134
  {
121
- if(ressource.model)
135
+ if(resource.model)
122
136
  {
123
- options[ressource.id] = { value: ressource.id, label: ressource.name + " ("+ressource.model+")" };
137
+ options[resource.id] = { value: resource.id, label: resource.name + " ("+resource.model+")" };
124
138
  }
125
139
  else
126
140
  {
127
- options[ressource.id] = { value: ressource.id, label: ressource.name };
141
+ options[resource.id] = { value: resource.id, label: resource.name };
128
142
  }
129
143
  }
130
144
  });
@@ -205,4 +219,4 @@
205
219
  }
206
220
  }
207
221
  });
208
- </script>
222
+ </script>
@@ -50,7 +50,7 @@ module.exports = function(RED)
50
50
  {
51
51
  let currentState = bridge.get("group", info.id, { colornames: config.colornamer ? true : false });
52
52
 
53
- // RESSOURCE FOUND?
53
+ // RESOURCE FOUND?
54
54
  if(currentState !== false)
55
55
  {
56
56
  // NOT IN UNIVERAL MODE? -> CHANGE UI STATES
@@ -102,14 +102,19 @@ module.exports = function(RED)
102
102
  send = send || function() { scope.send.apply(scope,arguments); }
103
103
 
104
104
  // SAVE LAST COMMAND
105
- scope.lastCommand = msg;
105
+ scope.lastCommand = RED.util.cloneMessage(msg);
106
106
 
107
107
  // CREATE PATCH
108
108
  let patchObject = {};
109
109
 
110
110
  // DEFINE SENSOR ID & CURRENT STATE
111
- const tempGroupID = (typeof msg.topic != 'undefined' && msg.topic.length > 0) ? msg.topic : config.groupid;
111
+ const tempGroupID = (!config.groupid && typeof msg.topic != 'undefined' && bridge.validResourceID.test(msg.topic) === true) ? msg.topic : config.groupid;
112
112
  let currentState = bridge.get("group", tempGroupID, { colornames: config.colornamer ? true : false });
113
+ if(!currentState)
114
+ {
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
+ return false;
117
+ }
113
118
 
114
119
  // CHECK IF LIGHT ID IS SET
115
120
  if(!tempGroupID)
@@ -88,6 +88,19 @@
88
88
  buttonIcon.removeClass("fa-pencil");
89
89
  buttonIcon.addClass("fa-search");
90
90
  }
91
+
92
+ function sortResourcesBy(prop, resources)
93
+ {
94
+ return resources.sort((a, b) => {
95
+ if ( a[prop] < b[prop] ){
96
+ return -1;
97
+ }
98
+ if ( a[prop] > b[prop] ){
99
+ return 1;
100
+ }
101
+ return 0;
102
+ });
103
+ }
91
104
 
92
105
  function searchAndSelect()
93
106
  {
@@ -102,10 +115,11 @@
102
115
  var notification = RED.notify(scope._("hue-light.config.searching"), { type: "compact", modal: true, fixed: true });
103
116
 
104
117
  // GET THE LIGHTS
105
- $.get('hue/ressources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "light" })
118
+ $.get('hue/resources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "light" })
106
119
  .done( function(data) {
107
- var allRessources = JSON.parse(data);
108
- if(allRessources.length <= 0)
120
+ var allResources = JSON.parse(data);
121
+ allResources = sortResourcesBy('name', allResources);
122
+ if(allResources.length <= 0)
109
123
  {
110
124
  notification.close();
111
125
  RED.notify(scope._("hue-light.config.none-found"), { type: "error" });
@@ -113,15 +127,15 @@
113
127
  }
114
128
 
115
129
  // SET OPTIONS
116
- allRessources.forEach(function(ressource)
130
+ allResources.forEach(function(resource)
117
131
  {
118
- if(ressource.model)
132
+ if(resource.model)
119
133
  {
120
- options[ressource.id] = { value: ressource.id, label: ressource.name + " ("+ressource.model+")" };
134
+ options[resource.id] = { value: resource.id, label: resource.name + " ("+resource.model+")" };
121
135
  }
122
136
  else
123
137
  {
124
- options[ressource.id] = { value: ressource.id, label: ressource.name };
138
+ options[resource.id] = { value: resource.id, label: resource.name };
125
139
  }
126
140
  });
127
141
 
@@ -201,4 +215,4 @@
201
215
  }
202
216
  }
203
217
  });
204
- </script>
218
+ </script>
@@ -47,7 +47,7 @@ module.exports = function(RED)
47
47
  {
48
48
  let currentState = bridge.get("light", info.id, { colornames: config.colornamer ? true : false });
49
49
 
50
- // RESSOURCE FOUND?
50
+ // RESOURCE FOUND?
51
51
  if(currentState !== false)
52
52
  {
53
53
  // SEND MESSAGE
@@ -115,14 +115,19 @@ module.exports = function(RED)
115
115
  done = done || function() { scope.done.apply(scope,arguments); }
116
116
 
117
117
  // SAVE LAST COMMAND
118
- scope.lastCommand = msg;
118
+ scope.lastCommand = RED.util.cloneMessage(msg);
119
119
 
120
120
  // CREATE PATCH
121
121
  let patchObject = {};
122
122
 
123
123
  // DEFINE SENSOR ID & CURRENT STATE
124
- const tempLightID = (typeof msg.topic != 'undefined' && msg.topic.length > 0) ? msg.topic : config.lightid;
124
+ const tempLightID = (!config.lightid && typeof msg.topic != 'undefined' && bridge.validResourceID.test(msg.topic) === true) ? msg.topic : config.lightid;
125
125
  let currentState = bridge.get("light", tempLightID, { colornames: config.colornamer ? true : false });
126
+ if(!currentState)
127
+ {
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
+ return false;
130
+ }
126
131
 
127
132
  // CHECK IF LIGHT ID IS SET
128
133
  if(!tempLightID)
@@ -81,6 +81,19 @@
81
81
  buttonIcon.removeClass("fa-pencil");
82
82
  buttonIcon.addClass("fa-search");
83
83
  }
84
+
85
+ function sortResourcesBy(prop, resources)
86
+ {
87
+ return resources.sort((a, b) => {
88
+ if ( a[prop] < b[prop] ){
89
+ return -1;
90
+ }
91
+ if ( a[prop] > b[prop] ){
92
+ return 1;
93
+ }
94
+ return 0;
95
+ });
96
+ }
84
97
 
85
98
  function searchAndSelect()
86
99
  {
@@ -95,10 +108,11 @@
95
108
  var notification = RED.notify(scope._("hue-motion.config.searching"), { type: "compact", modal: true, fixed: true });
96
109
 
97
110
  // GET THE SENSORS
98
- $.get('hue/ressources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "motion" })
111
+ $.get('hue/resources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "motion" })
99
112
  .done( function(data) {
100
- var allRessources = JSON.parse(data);
101
- if(allRessources.length <= 0)
113
+ var allResources = JSON.parse(data);
114
+ allResources = sortResourcesBy('name', allResources);
115
+ if(allResources.length <= 0)
102
116
  {
103
117
  notification.close();
104
118
  RED.notify(scope._("hue-motion.config.none-found"), { type: "error" });
@@ -106,15 +120,15 @@
106
120
  }
107
121
 
108
122
  // SET OPTIONS
109
- allRessources.forEach(function(ressource)
123
+ allResources.forEach(function(resource)
110
124
  {
111
- if(ressource.model)
125
+ if(resource.model)
112
126
  {
113
- options[ressource.id] = { value: ressource.id, label: ressource.name + " ("+ressource.model+")" };
127
+ options[resource.id] = { value: resource.id, label: resource.name + " ("+resource.model+")" };
114
128
  }
115
129
  else
116
130
  {
117
- options[ressource.id] = { value: ressource.id, label: ressource.name };
131
+ options[resource.id] = { value: resource.id, label: resource.name };
118
132
  }
119
133
  });
120
134
 
@@ -194,4 +208,4 @@
194
208
  }
195
209
  }
196
210
  });
197
- </script>
211
+ </script>
@@ -40,7 +40,7 @@ module.exports = function(RED)
40
40
  {
41
41
  let currentState = bridge.get("motion", info.id);
42
42
 
43
- // RESSOURCE FOUND?
43
+ // RESOURCE FOUND?
44
44
  if(currentState !== false)
45
45
  {
46
46
  // SEND MESSAGE
@@ -94,14 +94,25 @@ module.exports = function(RED)
94
94
  done = done || function() { scope.done.apply(scope,arguments); }
95
95
 
96
96
  // SAVE LAST COMMAND
97
- scope.lastCommand = msg;
97
+ scope.lastCommand = RED.util.cloneMessage(msg);
98
98
 
99
99
  // CREATE PATCH
100
100
  let patchObject = {};
101
101
 
102
102
  // DEFINE SENSOR ID & CURRENT STATE
103
- const tempSensorID = (typeof msg.topic != 'undefined' && msg.topic.length > 0) ? msg.topic : config.sensorid;
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
+
104
110
  let currentState = bridge.get("motion", tempSensorID);
111
+ if(!currentState)
112
+ {
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
+ return false;
115
+ }
105
116
 
106
117
  // GET CURRENT STATE
107
118
  if( (typeof msg.payload != 'undefined' && typeof msg.payload.status != 'undefined') || (typeof msg.__user_inject_props__ != 'undefined' && msg.__user_inject_props__ == "status") )
@@ -123,10 +134,10 @@ module.exports = function(RED)
123
134
  }
124
135
 
125
136
  // TURN ON / OFF
126
- if((msg.payload === true || msg.payload === false) && (msg.payload !== currentState.payload.active))
137
+ if((msg.payload === true || msg.payload === false) && (msg.payload != currentState.payload.active))
127
138
  {
128
139
  // PREPARE PATCH
129
- patchObject.enabled = msg.payload;
140
+ patchObject["enabled"] = (msg.payload == true);
130
141
  }
131
142
 
132
143
  //
@@ -81,6 +81,19 @@
81
81
  buttonIcon.removeClass("fa-pencil");
82
82
  buttonIcon.addClass("fa-search");
83
83
  }
84
+
85
+ function sortResourcesBy(prop, resources)
86
+ {
87
+ return resources.sort((a, b) => {
88
+ if ( a[prop] < b[prop] ){
89
+ return -1;
90
+ }
91
+ if ( a[prop] > b[prop] ){
92
+ return 1;
93
+ }
94
+ return 0;
95
+ });
96
+ }
84
97
 
85
98
  function searchAndSelect()
86
99
  {
@@ -95,10 +108,11 @@
95
108
  var notification = RED.notify(scope._("hue-rules.config.searching"), { type: "compact", modal: true, fixed: true });
96
109
 
97
110
  // GET THE SENSORS
98
- $.get('hue/ressources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "rule" })
111
+ $.get('hue/resources', { bridge: bridgeConfig.bridge, key: bridgeConfig.key, type: "rule" })
99
112
  .done( function(data) {
100
- var allRessources = JSON.parse(data);
101
- if(allRessources.length <= 0)
113
+ var allResources = JSON.parse(data);
114
+ allResources = sortResourcesBy('name', allResources);
115
+ if(allResources.length <= 0)
102
116
  {
103
117
  notification.close();
104
118
  RED.notify(scope._("hue-rules.config.none-found"), { type: "error" });
@@ -106,9 +120,9 @@
106
120
  }
107
121
 
108
122
  // SET OPTIONS
109
- allRessources.forEach(function(ressource)
123
+ allResources.forEach(function(resource)
110
124
  {
111
- options[ressource.id] = { value: ressource.id, label: ressource.name };
125
+ options[resource.id] = { value: resource.id, label: resource.name };
112
126
  });
113
127
 
114
128
  // SELECT CURRENT VALUE
@@ -187,4 +201,4 @@
187
201
  }
188
202
  }
189
203
  });
190
- </script>
204
+ </script>
@@ -40,7 +40,7 @@ module.exports = function(RED)
40
40
  {
41
41
  let currentState = bridge.get("rule", info.id);
42
42
 
43
- // RESSOURCE FOUND?
43
+ // RESOURCE FOUND?
44
44
  if(currentState !== false)
45
45
  {
46
46
  // NOT IN UNIVERAL MODE? -> CHANGE UI STATES
@@ -84,14 +84,25 @@ module.exports = function(RED)
84
84
  done = done || function() { scope.done.apply(scope,arguments); }
85
85
 
86
86
  // SAVE LAST COMMAND
87
- scope.lastCommand = msg;
87
+ scope.lastCommand = RED.util.cloneMessage(msg);
88
88
 
89
89
  // CREATE PATCH
90
90
  let patchObject = {};
91
91
 
92
92
  // DEFINE SENSOR ID & CURRENT STATE
93
- const tempRuleID = (typeof msg.topic != 'undefined' && msg.topic.length > 0) ? msg.topic : config.ruleid;
93
+ const tempRuleID = (!config.ruleid && typeof msg.topic != 'undefined' && isNaN(msg.topic) == false) ? msg.topic : config.ruleid;
94
+ if(!tempRuleID)
95
+ {
96
+ scope.error("Please submit a valid rule ID.");
97
+ return false;
98
+ }
99
+
94
100
  let currentState = bridge.get("rule", "rule_" + tempRuleID);
101
+ if(!currentState)
102
+ {
103
+ scope.error("The rule 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..");
104
+ return false;
105
+ }
95
106
 
96
107
  // CONTROL RULE
97
108
  if(msg.payload === true || msg.payload === false)
@@ -100,7 +111,7 @@ module.exports = function(RED)
100
111
  patchObject["status"] = (msg.payload == true) ? 'enabled' : 'disabled';
101
112
 
102
113
  // PATCH!
103
- bridge.patch("rules", "/rules/"+config.ruleid, patchObject, 1)
114
+ bridge.patch("rules", "/rules/"+tempRuleID, patchObject, 1)
104
115
  .then(function(response) { bridge.refetchRule(tempRuleID); })
105
116
  .catch(function(errors) { scope.error(errors); });
106
117