hueget 0.6.6 → 0.7.1

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,16 @@ See the [Readme file](https://github.com/jsiegenthaler/hueget/blob/master/README
4
4
 
5
5
  # Bug Fixes and Improvements
6
6
 
7
+ ## 0.7.1 (2024-04-06)
8
+ * Bumped dependencies: "axios": "^1.6.8"
9
+ * Bumped dependencies: "express": "^4.19.2"
10
+ * Bumped dependencies: "stdio": "^2.1.3"
11
+
12
+
13
+ ## 0.7.0 (2024-01-06)
14
+ * Added toggle capability for lights and groups
15
+ * Bumped dependencies: "axios": "^1.6.5"
16
+
7
17
  ## 0.6.6 (2023-11-27)
8
18
  * Added some more README.md improvements
9
19
 
package/README.md CHANGED
@@ -28,6 +28,9 @@ Flash your lights in the entire house when the doorbell rings. I have a Shelly1
28
28
  ## Control Hue Lights directly from Shelly Motion Sensors
29
29
  Anything that can call a url when triggered - such as a Shelly Motion Sensor - can be used to turn the lights on and off again. Make sure the motion sensor calls a url to turn lights on, and a url to turn lights off. The Shelly Motion Sensor is ideal for this, as you can activate call urls for different motion triggers.
30
30
 
31
+ ## Toggle lights from a Shelly Button 1
32
+ Toggle a light or group of lights from a button that sends a non-changing URL. The ```toggle``` command is perfect for any pushbutton controller that does not know (or can not know) the current light state, and only sends a non-changing static URL, such as a Shelly Button 1.
33
+
31
34
  ## Be Home Soon Alert
32
35
  Flash lights in a room or in any group (zone, room) when someone comes home. The ```alert=lselect``` command is perfect to generate a 15 second long flash without any extra programming. Just call the URL from Apple HomeKit automations when a person arrives in your geofence.
33
36
 
@@ -81,7 +84,7 @@ $ node /home/pi/node_modules/hueget/hueget.js -i 192.168.0.101 -u UBxWZChHseyjeF
81
84
  ```
82
85
  A successful start of hueget (using the above command to specify ip address 192.168.0.100 and port 1234) will show:
83
86
  ```
84
- hueget v0.6.2
87
+ hueget v0.7.0
85
88
  commands will be sent to 192.168.0.101 with username UBxWZChHseyjeFwAkwgbdQ08x9XASWpanZZVg-mj
86
89
  listening on port 1234
87
90
  ```
@@ -144,6 +147,7 @@ Examples:
144
147
  * Turn light 31 on at 50% brightness: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/31/state?on=true&bri=50
145
148
  * Turn light 31 on at 100% brightness: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/31/state?on=true&bri=100
146
149
  * Turn light 31 on at 100% brightness, 0.5,0.6 xy: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/31/state?on=true&bri=100&xy=[0.5%2c0.6]
150
+ * Toggle light 31: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/31/toggle
147
151
  * Identify light 31 with a single blink: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/31/state?alert=select
148
152
  * Identify light 31 with 15 seconds of blinking: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/31/state?alert=lselect
149
153
 
@@ -151,12 +155,14 @@ Examples:
151
155
  ### Group 0 (a special group for all lights in your home)
152
156
  * Turn group 0 on: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/0/action?on=true
153
157
  * Turn group 0 off: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/0/action?on=false
158
+ * Toggle group 0: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/0/toggle
154
159
  * Identify group 0 with 15 seconds of blinking: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/0/action?alert=lselect
155
160
 
156
161
 
157
162
  ### Group 2 (example)
158
163
  * Turn group 2 on: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2/action?on=true
159
164
  * Turn group 2 off: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2/action?on=false
165
+ * Toggle group 2: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2/toggle
160
166
  * Turn group 2 on at 50% brightness: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2/action?on=true&bri=50
161
167
  * Turn group 2 on at 100% brightness: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2/action?on=true&bri=100
162
168
  * Turn group 2 on at 100% brightness, 0.5,0.6 xy: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2/state?on=true&bri=100&xy=[0.5%2c0.6]
@@ -165,7 +171,15 @@ Examples:
165
171
 
166
172
  Groups are collections of lights, and are used for Rooms and Zones in the Hue app.
167
173
 
168
- # Supported Keywords
174
+ ## Special Commands
175
+ The hueget server supports a special toggle command, which does not exist natively in the Philips Hue bridge. This toggles (changes the state) of a specified light or a group, allowing you to toggle the light/group state with a single URL.
176
+
177
+ Syntax:
178
+ * Toggle light 1: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/1/toggle
179
+ * Toggle group 2: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2/toggle
180
+
181
+
182
+ ## Supported Keywords
169
183
  The API is transparent to all Philips Hue keywords. It expects all name=value pairs to be separated by a comma. If any comma is required inside a value, eg: for the xy command which expects a value array, then you must url encode the comma to %2c.
170
184
 
171
185
  The full JSON response for a light looks like this:
@@ -178,12 +192,12 @@ The full JSON response for a group looks like this:
178
192
  {"name":"Lounge","lights":["9","1","2"],"sensors":[],"type":"Room","state":{"all_on":false,"any_on":false},"recycle":false,"class":"Lounge","action":{"on":false,"bri":0,"hue":7800,"sat":138,"effect":"none","xy":[0.5302,0.392],"ct":153,"alert":"select","colormode":"xy"}}
179
193
  ```
180
194
  The most common action keywords for state or group are:
181
- on, bri, hue, sat, effect, xy, ct, alert, colormode, mode (lights only)
195
+ on, bri, hue, sat, effect, xy, ct, alert, colormode, mode (lights only).
182
196
  More keywords exist, see the [API documentation](#api-documentation).
183
197
 
184
198
  ## on (get and set)
185
199
  Turn a light on or off. On=true, Off=false.
186
- Valid for light or group.
200
+ Valid for light or group. A group also supports all_on and any_on.
187
201
 
188
202
  ## bri (get and set)
189
203
  The brightness value to set the light to. Brightness is a scale from 1 (the minimum the light is capable of) to 254 (the maximum).
@@ -247,7 +261,7 @@ See the [API documentation](#api-documentation).
247
261
 
248
262
  ## API Documentation
249
263
  For full details of the control capabilities, please see the [official Philips Hue API reference](https://developers.meethue.com/develop/hue-api/).
250
- An [alternative unoffical reference](http://www.burgestrand.se/hue-api/), somewhat outdated also exists.
264
+ An [alternative unoffical reference](http://www.burgestrand.se/hue-api/), somewhat outdated, also exists.
251
265
 
252
266
 
253
267
  # Finding your Light or Group ids
@@ -265,6 +279,6 @@ Go backwards in the text until you find the keyword **state**, this is at the st
265
279
  ... ,"31":{"state":{"on":true,"bri":100,"hue":65396 ...
266
280
  ```
267
281
 
268
- Use the same method for groups to find the group id of the room you wish to control. Note that group id 0 is a special group containing all lights in the system, and is not returned by the ‘get all groups’ command. Group 0 is not visible, and cannot be created, modified or deleted using the API.
282
+ Use the same method for groups to find the group id of the room you wish to control. Note that group id 0 is a special group containing all lights in the system, and is not returned by the ‘get all groups’ command. Group 0 is not visible, and cannot be created, modified or deleted using the API, but group 0 can be controlled by the API.
269
283
 
270
284
 
package/hueget.js CHANGED
@@ -96,9 +96,12 @@ app.use('/api/' + options.username, (req, res) => {
96
96
  break;
97
97
  }
98
98
  //console.log('expectedCommand', expectedCommand );
99
- if (!command.startsWith(expectedCommand)) { throw errPrefix + 'unknown command "' + command + '", expecting "' + expectedCommand + '": "' + req.url + '"'; }
100
- if (!command.includes(expectedCommand + '?')) { throw errPrefix + 'query character "?" missing in "' + command + '", expecting "' + expectedCommand + '?<query>": "' + req.url + '"'; }
101
- if (command.endsWith(expectedCommand + '?')) { throw errPrefix + 'query missing in "' + command + '", expecting "' + expectedCommand + '?<query>": "' + req.url + '"'; }
99
+ // toggle is a special case, raise error for anything else that does not fit the syntax
100
+ if (command != 'toggle') {
101
+ if (!command.startsWith(expectedCommand)) { throw errPrefix + 'unknown command "' + command + '", expecting "' + expectedCommand + '": "' + req.url + '"'; }
102
+ if (!command.includes(expectedCommand + '?')) { throw errPrefix + 'query character "?" missing in "' + command + '", expecting "' + expectedCommand + '?<query>": "' + req.url + '"'; }
103
+ if (command.endsWith(expectedCommand + '?')) { throw errPrefix + 'query missing in "' + command + '", expecting "' + expectedCommand + '?<query>": "' + req.url + '"'; }
104
+ }
102
105
  }
103
106
 
104
107
 
@@ -137,41 +140,91 @@ app.use('/api/' + options.username, (req, res) => {
137
140
  result = result + ',"' + pair[0] + '":' + pairValue;
138
141
  });
139
142
  result = result.replace('{,','{') + '}'; // clean up, add brackets
140
- //console.log('result', result );
143
+ console.log('result', result );
141
144
  dataObj = JSON.parse(result);
142
145
  }
143
146
 
144
147
 
148
+
149
+
145
150
  // if a dataObj exists, send PUT; otherwise, send a GET
146
151
  // GET http://192.168.0.101/api/<username>/lights/31
147
152
  // PUT http://192.168.0.101/api/<username>/lights/31/state --data "{""on"":true}"
148
153
  var url = 'http://' + options.ip + '/api/' + options.username + '/' + resource;
149
154
  if (id) { url = url + '/' + id; } // add id if supplied
150
- if (dataObj){
151
- console.log('sending PUT: %s %s', url + '/' + expectedCommand, dataObj || '');
152
- axios.put(url + '/' + expectedCommand, dataObj)
155
+
156
+
157
+ // special handling for toggle command, this toggles a light or group state
158
+ if (command == 'toggle') {
159
+ console.log('toggling current state')
160
+ // Get actual state
161
+ console.log('sending GET: %s', url);
162
+ axios.get(url)
153
163
  .then(response => {
154
- console.log('PUT response:', response.status, response.statusText, JSON.stringify(response.data) );
155
- res.json(response.data);
156
- })
164
+ // for lights /lights/<id> state = on true/false
165
+ // for groups, /groups/<id> state = all_on true/false
166
+ switch(resource) {
167
+ case 'lights':
168
+ console.log('GET response:', response.status, response.statusText, "state:on="+response.data["state"]["on"] );
169
+ state = !response.data["state"]["on"] // get the current on state , as a boolean, and invert it
170
+ expectedCommand = 'state'
171
+ break;
172
+ case 'groups':
173
+ console.log('GET response:', response.status, response.statusText, "state:all_on="+response.data["state"]["all_on"] );
174
+ state = !response.data["state"]["all_on"] // get the current all_on state, as a boolean, and invert it
175
+ expectedCommand = 'action'
176
+ break;
177
+ }
178
+ // toggle light or group state
179
+ // lights: http://localhost:3000/api/<username>/lights/31/state?on=true
180
+ // groups: http://localhost:3000/api/<username>/groups/0/action?on=true
181
+ console.log('sending PUT: %s%s', url + '/' + "state?on=", state.toString() || '');
182
+ axios.put(url + '/' + expectedCommand,'{"on":' + state.toString() + '}')
183
+ .then(response => {
184
+ console.log('PUT response:', response.status, response.statusText, JSON.stringify(response.data) );
185
+ res.json(response.data);
186
+ })
187
+ .catch(error => {
188
+ const errText = error.syscall + ' ' + error.code + ' ' + error.address + ':' + error.port;
189
+ console.log('PUT error:', errText);
190
+ res.json({ error: errText });
191
+ });
192
+ })
157
193
  .catch(error => {
158
194
  const errText = error.syscall + ' ' + error.code + ' ' + error.address + ':' + error.port;
159
- console.log('PUT error:', errText);
195
+ console.log('GET error:', errText);
160
196
  res.json({ error: errText });
161
197
  });
162
- } else {
163
- console.log('sending GET: %s', url);
164
- axios.get(url)
198
+
199
+
200
+ // normal handling for non-toggle commands
201
+ } else {
202
+ if (dataObj){
203
+ console.log('sending PUT: %s %s', url + '/' + expectedCommand, dataObj || '');
204
+ axios.put(url + '/' + expectedCommand, dataObj)
165
205
  .then(response => {
166
- console.log('GET response:', response.status, response.statusText, JSON.stringify(response.data) );
206
+ console.log('PUT response:', response.status, response.statusText, JSON.stringify(response.data) );
167
207
  res.json(response.data);
168
208
  })
169
209
  .catch(error => {
170
210
  const errText = error.syscall + ' ' + error.code + ' ' + error.address + ':' + error.port;
171
- console.log('GET error:', errText);
211
+ console.log('PUT error:', errText);
172
212
  res.json({ error: errText });
173
213
  });
214
+ } else {
215
+ console.log('sending GET: %s', url);
216
+ axios.get(url)
217
+ .then(response => {
218
+ console.log('GET response:', response.status, response.statusText, JSON.stringify(response.data) );
219
+ res.json(response.data);
220
+ })
221
+ .catch(error => {
222
+ const errText = error.syscall + ' ' + error.code + ' ' + error.address + ':' + error.port;
223
+ console.log('GET error:', errText);
224
+ res.json({ error: errText });
225
+ });
174
226
  }
227
+ }
175
228
  return;
176
229
 
177
230
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hueget",
3
- "version": "0.6.6",
3
+ "version": "0.7.1",
4
4
  "description": "A simple API that converts the Philips Hue API PUT to GET requests, allowing control of Philips Hue lights via http GET requests",
5
5
  "main": "hueget.js",
6
6
  "scripts": {
@@ -25,9 +25,9 @@
25
25
  "author": "Jochen Siegenthaler (https://github.com/jsiegenthaler)",
26
26
  "license": "ISC",
27
27
  "dependencies": {
28
- "axios": "^1.6.2",
29
- "express": "^4.18.2",
30
- "stdio": "^2.1.1"
28
+ "axios": "^1.6.8",
29
+ "express": "^4.19.2",
30
+ "stdio": "^2.1.3"
31
31
  },
32
32
  "engines": {
33
33
  "node": "^20"