hueget 0.7.6 → 1.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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,9 @@ See the [Readme file](https://github.com/jsiegenthaler/hueget/blob/master/README
4
4
 
5
5
  # Bug Fixes and Improvements
6
6
 
7
+ ## 1.0.0 (2025-01-01)
8
+ * Added support for further controllable api endpoints: schedules,scenes,sensors,rules,resourcelinks,capabilities
9
+
7
10
 
8
11
  ## 0.7.6 (2024-12-13)
9
12
  * Added Docker config (thanks @Yannis4444)
package/README.md CHANGED
@@ -9,13 +9,11 @@
9
9
  A simple API to control Philips Hue lamps with http GET requests.
10
10
 
11
11
  # Background
12
- The existing Philips Hue REST API requires a PUT request to control the Hue lights and groups.
12
+ The existing Philips Hue REST API requires a PUT request to control the Hue lights, groups, sensors and other resources of the Hue system.
13
13
 
14
- I needed GET, so I made a simple API to translate from GET to PUT. It also supports the standard GET command so you can use hueget for both.
14
+ I had a specific use case where I could only use GET requests, so I made a simple API to translate from GET to PUT. It also supports the standard GET command so you can use hueget for both GET and PUT.
15
15
 
16
- hueget suports controlling lights as well as groups. A group is a collection of a number of lights, which in the Philips Hue app appears as a room.
17
-
18
- This is my first ever API javascript program, so if you see any way it can be improved, I'd be happy to receive your suggestions.
16
+ hueget supports controlling lights, groups, sensors and more. A group is a collection of a number of lights, which in the Philips Hue app appears as a room. Sensors are devices such as the daylight sensor, the geofence sensor, motion sensors (which include light level and temperature) and switch sensors.
19
17
 
20
18
  If you like this tool, consider buying me a coffee!<br>
21
19
  <a target="blank" href="https://ko-fi.com/jsiegenthaler"><img src="https://img.shields.io/badge/Ko--Fi-Buy%20me%20a%20coffee-29abe0.svg?logo=ko-fi"/></a>
@@ -23,16 +21,16 @@ If you like this tool, consider buying me a coffee!<br>
23
21
  # Creative Ways to use hueget
24
22
 
25
23
  ## Visual Door Bell
26
- Flash your lights in the entire house when the doorbell rings. I have a Shelly1 as my doorbell. The doorbell connects to the Shelly1 SW input using a relay on the doorbell buzzer. Thus when the doorbell button is pressed, the Shelly1 sees an input, and calls a url, which flashes a group of lights for 15 seconds using the ```alert=lselect``` command. I use the Philips Hue app to determine what lights should be in the group.
24
+ Flash your lights in the entire house when the doorbell rings. I have a Shelly1 as my doorbell. The doorbell connects to the Shelly1 SW input using a relay on the doorbell buzzer. Thus when the doorbell button is pressed, the Shelly1 sees an input, and calls a url, which flashes a group of lights for 15 seconds using the `alert=lselect` command. I use the Philips Hue app to determine what lights should be in the group.
27
25
 
28
26
  ## Control Hue Lights directly from Shelly Motion Sensors
29
27
  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
28
 
31
29
  ## 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.
30
+ 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
32
  ## Be Home Soon Alert
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
+ 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.
36
34
 
37
35
 
38
36
  # Installing hueget
@@ -84,7 +82,7 @@ $ node /home/pi/node_modules/hueget/hueget.js -i 192.168.0.101 -u UBxWZChHseyjeF
84
82
  ```
85
83
  A successful start of hueget (using the above command to specify ip address 192.168.0.100 and port 1234) will show:
86
84
  ```
87
- hueget v0.7.6
85
+ hueget v1.0.0
88
86
  commands will be sent to 192.168.0.101 with username UBxWZChHseyjeFwAkwgbdQ08x9XASWpanZZVg-mj
89
87
  listening on port 1234
90
88
  ```
@@ -121,7 +119,7 @@ For more information about pm2, see https://github.com/Unitech/pm2
121
119
 
122
120
 
123
121
  # Getting your Philips Hue Bridge API Username
124
- If you have [Homebridge](https://homebridge.io/), and the [homebridge-hue](https://github.com/ebaauw/homebridge-hue) plugin, look at the **users** section of the hue config. You will see the Hue bridge MAC address folowed by the Hue bridge api username
122
+ If you have [Homebridge](https://homebridge.io/), and the [homebridge-hue](https://github.com/ebaauw/homebridge-hue) plugin, look at the **users** section of the hue config. You will see the Hue bridge MAC address followed by the Hue bridge api username
125
123
  ```
126
124
  "users": {
127
125
  "ECB5FAFFFEFFFFFF": "yourPhilipsHueBridgeUsername"
@@ -132,6 +130,9 @@ The username will look something like this:
132
130
  UBxWZChHseyjeFwAkwgbdQ08x9XASWpanZZVg-mj
133
131
  ```
134
132
 
133
+ Otherwise, if you do not have the homebridge-hue plugin installed, you need to create a new api username using the instructions shown here: https://developers.meethue.com/develop/get-started-2/ (this page does not require a Hue Developer Account).
134
+
135
+
135
136
  # Running hueget with Docker (optional, only if you use a Docker environment)
136
137
  You can run hueget easily using Docker and Docker Compose. This approach simplifies the setup in a Docker environment and ensures hueget is isolated and always running reliably.
137
138
 
@@ -145,17 +146,25 @@ You can run hueget easily using Docker and Docker Compose. This approach simplif
145
146
  ```bash
146
147
  docker compose up -d
147
148
  ```
149
+
148
150
 
149
-
150
- # Reading the Status of your Hue Lights or Groups with hueget
151
- Enter a URL (in the format shown below) into your browser and press Enter. The ip address is the ip address of the device running hueget, eg: a raspberry pi.
151
+ # Reading the Status of your Hue Lights, Groups, Sensors and other Resources with hueget
152
+ Enter a URL (in the format shown below) into your browser and press Enter. The ip address is the ip address of the device running hueget, e.g.: a raspberry pi.
152
153
  Examples:
153
154
 
154
155
  * Get status of light 31: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/31
155
156
  * Get status of group 2: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2
157
+ * Get status of sensor 1: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/sensors/1
158
+ * Get status of resourcename 1: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/resourcename/1
159
+
160
+ # Get the Capabilities of your Hue Bridge with hueget
161
+ The capabilities api endpoint shows how many lights, sensors, groups, scenes, schedules, rules, resourcelinks and other resources are available and how many exist in total. This is very useful to determine how many resources are configured and being used.
162
+ Example:
163
+
164
+ * Get capabilities of the Hue bridge: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/capabilities
156
165
 
157
- # Controlling your Hue Lights or Groups with hueget
158
- Enter a URL (in the format shown below) into your browser and press Enter. The ip address is the ip address of the device running hueget, eg: a raspberry pi.
166
+ # Controlling your Hue Lights, Groups or Sensors with hueget
167
+ Enter a URL (in the format shown below) into your browser and press Enter. The ip address is the ip address of the device running hueget, e.g.: a raspberry pi.
159
168
  Examples:
160
169
  ## Lights
161
170
  ### Light 31 (example)
@@ -188,29 +197,101 @@ Examples:
188
197
 
189
198
  Groups are collections of lights, and are used for Rooms and Zones in the Hue app.
190
199
 
191
- ## Special Commands
192
- 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.
200
+
201
+ ## Sensors
202
+ ### Sensor 1 (the daylight sensor)
203
+ * Turn sensor 1 on: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/sensors/1/config?on=true
204
+ * Turn sensor 1 off: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/sensors/1/config?on=false
205
+ * Toggle sensor 1: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/sensors/1/toggle
206
+
207
+ ### Sensor 15 (example, a Hue motion sensor)
208
+ * Turn sensor 15 on: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/sensors/15/config?on=true
209
+ * Turn sensor 15 off: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/sensors/15/config?on=false
210
+ * Toggle sensor 15: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/sensors/15/toggle
211
+
212
+
213
+ ## Special Toggle Command for Lights, Groups and Sensors
214
+ 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 group or sensor, allowing you to toggle the light/group/sensor state with a single URL. Toggling only makes sense for items that have an on and off state, which is why it is currently restricted to lights, groups and sensors.
215
+
216
+ The toggling of a light, group or sensor is the same as turning it on or off in the Hue app, and thus applies to the `on` parameter of the relevant `state` (lights), `action` (groups) or `config` (sensors).
193
217
 
194
218
  Syntax:
195
219
  * Toggle light 1: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/1/toggle
196
220
  * Toggle group 2: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2/toggle
221
+ * Toggle sensor 15: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/sensors/15/toggle
222
+
197
223
 
224
+ ## Supported Command Keywords and Parameters
225
+ The API is transparent to all Philips Hue command keywords and parameters. It expects all parameter name=value pairs to be separated by a comma. If any comma is required inside a value, e.g.: for the xy command which expects a value array, then you must url encode the comma to %2c.
198
226
 
199
- ## Supported Keywords
200
- 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.
227
+ If you include a parameter that the Hue bridge does not understand, an error message will be returned from the Hue bridge. Example:
201
228
 
229
+ url: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/sensors/15/config?xxxx=on
230
+
231
+ Response:
232
+ ```
233
+ [{"error":{"type":6,"address":"/sensors/15/config/xxxx","description":"parameter, xxxx, not available"}}]
234
+ ```
235
+
236
+
237
+ ## Example JSON Responses
238
+ ### Lights
202
239
  The full JSON response for a light looks like this:
203
240
  ```
204
241
  {"1":{"state":{"on":false,"bri":198,"hue":5360,"sat":192,"effect":"none","xy":[0.5330,0.3870],"ct":500,"alert":"select","colormode":"xy","mode":"homeautomation","reachable":true},"swupdate":{"state":"noupdates","lastinstall":"2021-08-21T01:50:00"},"type":"Extended color light","name":"Standard Lamp","modelid":"LCA001","manufacturername":"Signify Netherlands B.V.","productname":"Hue color lamp","capabilities":{"certified":true,"control":{"mindimlevel":200,"maxlumen":800,"colorgamuttype":"C","colorgamut":[[0.6915,0.3083],[0.1700,0.7000],[0.1532,0.0475]],"ct":{"min":153,"max":500}},"streaming":{"renderer":true,"proxy":true}},"config":{"archetype":"floorshade","function":"mixed","direction":"omnidirectional","startup":{"mode":"safety","configured":true}},"uniqueid":"00:17:88:01:08:ff:ff:ff-0b","swversion":"1.90.1","swconfigid":"35F80D40","productid":"Philips-LCA001-4-A19ECLv6"}}
205
242
  ```
206
243
 
244
+ ### Groups
207
245
  The full JSON response for a group looks like this:
208
246
  ```
209
247
  {"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"}}
210
248
  ```
249
+
250
+ ### Sensors
251
+ The full JSON response for a sensor varies according to the sensor type. A few types are shown below:
252
+
253
+ #### Daylight
254
+ A Daylight sensor is a built-in sensor used for sunrise and sunset functions
255
+ ```
256
+ {"1":{"state":{"daylight":true,"lastupdated":"2025-01-01T07:12:00"},"config":{"on":true,"configured":true,"sunriseoffset":0,"sunsetoffset":0},"name":"Daylight","type":"Daylight","modelid":"PHDL00","manufacturername":"Signify Netherlands B.V.","swversion":"1.0"}
257
+ ```
258
+
259
+ #### Geofence
260
+ A Geofence sensor is a built-in sensor used for coming and leaving home functions
261
+ ```
262
+ "4":{"state":{"presence":true,"lastupdated":"2021-05-27T17:54:43"},"config":{"on":true,"reachable":true},"name":"John's iPhone","type":"Geofence","modelid":"HA_GEOFENCE","manufacturername":"Philips","swversion":"1.0","uniqueid":"L_02_AaRRM","recycle":false}
263
+ ```
264
+
265
+ #### ZLLPresence
266
+ A ZLLPresence sensor is the motion sensor component of a Hue Motion Sensor
267
+ ```
268
+ "15":{"state":{"presence":false,"lastupdated":"2025-01-01T09:09:13"},"swupdate":{"state":"noupdates","lastinstall":"2019-12-31T21:39:06"},"config":{"on":true,"battery":70,"reachable":true,"alert":"lselect","sensitivity":2,"sensitivitymax":2,"ledindication":false,"usertest":false,"pending":[]},"name":"Motion sensor 1","type":"ZLLPresence","modelid":"SML001","manufacturername":"Signify Netherlands B.V.","productname":"Hue motion sensor","swversion":"6.1.1.27575","uniqueid":"00:17:88:01:06:f5:1f:36-02-0406","capabilities":{"certified":true,"primary":true}},
269
+ ```
270
+
271
+ #### ZLLLightLevel
272
+ A ZLLLightLevel sensor is the ambient light sensor component of a Hue Motion Sensor
273
+ ```
274
+ "16":{"state":{"lightlevel":11427,"dark":false,"daylight":true,"lastupdated":"2025-01-01T09:10:17"},"swupdate":{"state":"noupdates","lastinstall":"2019-12-31T21:39:06"},"config":{"on":true,"battery":70,"reachable":true,"alert":"none","tholddark":2702,"tholdoffset":7000,"ledindication":false,"usertest":false,"pending":[]},"name":"Hue ambient light sensor 1","type":"ZLLLightLevel","modelid":"SML001","manufacturername":"Signify Netherlands B.V.","productname":"Hue ambient light sensor","swversion":"6.1.1.27575","uniqueid":"00:17:88:01:06:f5:1f:36-02-0400","capabilities":{"certified":true,"primary":false}},
275
+ ```
276
+
277
+ #### ZLLTemperature
278
+ A ZLLTemperature sensor is the temperature sensor component of a Hue Motion Sensor
279
+ ```
280
+ "17":{"state":{"temperature":2030,"lastupdated":"2025-01-01T09:08:13"},"swupdate":{"state":"noupdates","lastinstall":"2019-12-31T21:39:06"},"config":{"on":true,"battery":70,"reachable":true,"alert":"none","ledindication":false,"usertest":false,"pending":[]},"name":"Hue temperature sensor 1","type":"ZLLTemperature","modelid":"SML001","manufacturername":"Signify Netherlands B.V.","productname":"Hue temperature sensor","swversion":"6.1.1.27575","uniqueid":"00:17:88:01:06:f5:1f:36-02-0402","capabilities":{"certified":true,"primary":false}}
281
+ ```
282
+
283
+ #### ZLLSwitch
284
+ A ZLLSwitch sensor is the dimmer switch buttons of a Hue dimmer switch (original version)
285
+ ```
286
+ "79":{"state":{"buttonevent":1002,"lastupdated":"2024-12-31T21:19:34"},"swupdate":{"state":"noupdates","lastinstall":"2020-07-18T12:47:52"},"config":{"on":true,"battery":15,"reachable":true,"pending":[]},"name":"Hue dimmer switch","type":"ZLLSwitch","modelid":"RWL021","manufacturername":"Signify Netherlands B.V.","productname":"Hue dimmer switch","diversityid":"73bbabea-3420-499a-9856-46bf437e119b","swversion":"6.1.1.28573","uniqueid":"00:17:88:01:08:09:d4:cd-02-fc00","capabilities":{"certified":true,"primary":true,"inputs":[{"repeatintervals":[800],"events":[{"buttonevent":1000,"eventtype":"initial_press"},{"buttonevent":1001,"eventtype":"repeat"},{"buttonevent":1002,"eventtype":"short_release"},{"buttonevent":1003,"eventtype":"long_release"},{"buttonevent":1004,"eventtype":"long_press"}]},{"repeatintervals":[800],"events":[{"buttonevent":2000,"eventtype":"initial_press"},{"buttonevent":2001,"eventtype":"repeat"},{"buttonevent":2002,"eventtype":"short_release"},{"buttonevent":2003,"eventtype":"long_release"},{"buttonevent":2004,"eventtype":"long_press"}]},{"repeatintervals":[800],"events":[{"buttonevent":3000,"eventtype":"initial_press"},{"buttonevent":3001,"eventtype":"repeat"},{"buttonevent":3002,"eventtype":"short_release"},{"buttonevent":3003,"eventtype":"long_release"},{"buttonevent":3004,"eventtype":"long_press"}]},{"repeatintervals":[800],"events":[{"buttonevent":4000,"eventtype":"initial_press"},{"buttonevent":4001,"eventtype":"repeat"},{"buttonevent":4002,"eventtype":"short_release"},{"buttonevent":4003,"eventtype":"long_release"},{"buttonevent":4004,"eventtype":"long_press"}]}]}}
287
+ ```
288
+
289
+ ## Common Action Keywords for Lights and Groups
211
290
  The most common action keywords for state or group are:
291
+
212
292
  on, bri, hue, sat, effect, xy, ct, alert, colormode, mode (lights only).
213
- More keywords exist, see the [API documentation](#api-documentation).
293
+
294
+ For the full documentation of all keywords, see the [API documentation for lights](https://developers.meethue.com/develop/hue-api/lights-api/) and the [API documentation for groups](https://developers.meethue.com/develop/hue-api/groupds-api/).
214
295
 
215
296
  ## on (get and set)
216
297
  Turn a light on or off. On=true, Off=false.
@@ -226,7 +307,7 @@ The hue value to set the light to. The hue value is a wrapping value between 0 a
226
307
  Saturation of the light. 254 is the most saturated (colored) and 0 is the least saturated (white).
227
308
 
228
309
  ## xy (get and set)
229
- The xy values represent x and y coordinates of a color in CIE color space. The first value is the x coordinate and the second value is the y coordinate. Both x and y must be between 0 and 1, and will be rounded to 4 decimal places by the Hue bridge, eg: 0.666666 becomes 0.6667.
310
+ The xy values represent x and y coordinates of a color in CIE color space. The first value is the x coordinate and the second value is the y coordinate. Both x and y must be between 0 and 1, and will be rounded to 4 decimal places by the Hue bridge, e.g.: 0.666666 becomes 0.6667.
230
311
  If the specified coordinates are not in the CIE color space, the closest color to the coordinates will be chosen.
231
312
 
232
313
  When sending the xy array, you **must** url encode the comma to %2c (or %2C). Here is an example for "xy":\[0.25,0.52\] :
@@ -273,17 +354,32 @@ Increments or decrements the value of the xy. xy_inc is ignored if the xy attri
273
354
  Exact use unknown. Looks like it reflects an operating mode. Observed values are: homeautomation
274
355
 
275
356
 
276
- ## Further commands
277
- See the [API documentation](#api-documentation).
357
+ ## Common Config Keywords for Sensors
358
+ Sensors can have their state and config updated by the api. You can also update other parameters.
359
+
360
+ The state and config capabilities are dependent on the sensor type. The most common config keywords for sensors are:
361
+
362
+ on, battery, reachable, alert, tholddark, tholdoffset, sensitivity, sensitivitymax, ledindication, usertest
363
+
364
+ For the full documentation of all keywords, see the [API documentation for sensors](https://developers.meethue.com/develop/hue-api/5-sensors-api/).
365
+
366
+ ## on (get and set)
367
+ Turn a sensor on or off. On=true, Off=false. This is the same as enabling or disabling the sensor in the Hue app.
368
+ Valid for Daylight, Geofence, ZLLPresence, ZLLLightLevel, ZLLTemperature, ZLLSwitch and likely more.
369
+
370
+
371
+
278
372
 
279
373
  ## API Documentation
280
374
  For full details of the control capabilities, please see the [official Philips Hue API reference](https://developers.meethue.com/develop/hue-api/).
281
- An [alternative unoffical reference](http://www.burgestrand.se/hue-api/), somewhat outdated, also exists.
375
+
376
+ An [alternative unofficial reference](http://www.burgestrand.se/hue-api/), somewhat outdated, also exists.
282
377
 
283
378
 
284
- # Finding your Light or Group ids
285
- You need to know the light id or the group id of the light or group you wish to control.
286
- Go to http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights respectively http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups. You will see a JSON responce that looks like this (truncated here for brevity, only lights is shown. Groups is similar):
379
+ # Finding your Light, Group, Sensor or other Resource ids
380
+ You need to know the id of the resource (light, group, sensor etc) that you wish to control.
381
+ Ids can be either a numeric integer (generally starting at 0) or a string, depending on the resource.
382
+ Go to http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/resourcename. The resourcename is lights, groups, sensors, etc. You will see a JSON response that looks like this (truncated here for brevity, only lights is shown. Groups is similar):
287
383
  ```
288
384
  {"1":{"state":{"on":false,"bri":198,"hue":5360,"sat":192,"effect":"none","xy":[0.5330,0.3870],"ct":500," ...
289
385
  ```
@@ -291,11 +387,11 @@ Copy and paste the response into a text editor and format as JSON (or use an onl
291
387
  ```
292
388
  ... ,"type":"Extended color light","name":"Desk lamp","modelid":"LCT012", ...
293
389
  ```
294
- Go backwards in the text until you find the keyword **state**, this is at the start of the JSON text for the light. The light id is the number immediately before state. In this case, my light id is 31:
390
+ Go backwards in the text until you find the keyword **state**, this is at the start of the JSON text for the light. The light id is the value immediately before state. In this case, my light id is 31:
295
391
  ```
296
392
  ... ,"31":{"state":{"on":true,"bri":100,"hue":65396 ...
297
393
  ```
298
394
 
299
- 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.
395
+ Use the same method for other resources 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.
300
396
 
301
397
 
package/hueget.js CHANGED
@@ -61,19 +61,35 @@ app.use('/api/' + options.username, (req, res) => {
61
61
  const resource = (urlPathParts[1] || '').toLowerCase();
62
62
  const id = urlPathParts[2];
63
63
  const command = (urlPathParts[3] || '').toLowerCase();
64
- //console.log('resource', resource );
65
- //console.log('id', id );
66
- //console.log('command', command );
64
+ var commandParts = command.split('?'); // split on ? if exists, the put command is the first array index
65
+ var putCommand = commandParts[0]; // the possible PUT command
66
+ /*
67
+ // Debug:
68
+ console.log('commandParts[0]', commandParts[0] );
69
+ console.log('commandParts[1]', commandParts[1] );
70
+ console.log('resource', resource );
71
+ console.log('id', id );
72
+ console.log('command', command );
73
+ console.log('putCommand', putCommand );
74
+ */
67
75
 
68
76
  // throw error if resource is not supported
69
- if ( !((resource == 'lights') || (resource == 'groups')) ) {
70
- throw errPrefix + 'unknown resource "' + resource + '", expecting "lights" or "groups": "' + req.url + '"';
77
+ // more resources added in v1.0.0
78
+ const supportedResources = ['lights','groups','schedules','scenes','sensors','rules','resourcelinks','capabilities'];
79
+ //console.log(JSON.stringify(supportedResources));
80
+ //console.log(resource, supportedResources.indexOf(resource));
81
+ if (supportedResources.indexOf(resource) < 0) {
82
+ throw errPrefix + 'unknown resource "' + resource + '", expecting one of ' + JSON.stringify(supportedResources).replace('[', '').replace(']', '').replace('"', '') + ': "' + req.url + '"';
71
83
  }
72
84
 
73
- // get the id, throw error if not a number
74
- if ( (isNaN((id || '')) || (id == '')) ){ throw errPrefix + 'id "' + id + '" is not an integer: "' + req.url + '"';}
85
+ // get the id, throw error if not a number only for resources that need a numeric id
86
+ const resourcesWithIdInteger = ['lights','groups','sensors','rules','schedules'];
87
+ if (resourcesWithIdInteger.indexOf(resource) > 0) {
88
+ if ( (isNaN((id || '')) || (id == '')) ){ throw errPrefix + 'id "' + id + '" is not an integer: "' + req.url + '"';}
89
+ }
75
90
 
76
91
  // throw error if unexpected quantity of url components
92
+ // supported quantity of url components: up to 3
77
93
  // allowed:
78
94
  // /<resource>
79
95
  // /<resource>/<id>
@@ -82,45 +98,27 @@ app.use('/api/' + options.username, (req, res) => {
82
98
  throw errPrefix + (urlPathParts.length - 1).toString() + ' url path components found, expecting maximum 3: "' + req.url + '"';
83
99
  }
84
100
 
85
- // throw error if unexpected command
86
- // for lights /lights/<id>/state expectedCommand = state or nothing
87
- // for groups, /groups/<id>/action expectedCommand = action or nothing
88
- var expectedCommand;
89
- if (urlPathParts.length > 3) {
90
- switch(resource) {
91
- case 'lights':
92
- expectedCommand = 'state'
93
- break;
94
- case 'groups':
95
- expectedCommand = 'action'
96
- break;
97
- }
98
- //console.log('expectedCommand', expectedCommand );
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
- }
105
- }
106
-
101
+ // DEPRECATED throw error if unexpected command DEPRECATED
102
+ // as of 1.0.0, do not test the commands, as they vary a lot.
103
+ // So allow the hue bridge to reject a command if incorrect.
107
104
 
108
- // get the query parts, throw error if unexpected quantity
109
- const urlQueryParts = req.url.split('?');
110
- if ( (urlPathParts[0].toLowerCase() == expectedCommand) && (urlQueryParts.length != 2) ) {
111
- throw errPrefix + (urlQueryParts.length - 1).toString() + ' "?" delimiters found, expecting 1: "' + req.url + '"';
105
+ // throw error if unexpected quantity of ? delimiters
106
+ // get the commandParts parts, identified by the presence of a ? delimiter, throw error if unexpected quantity of delimiters exist
107
+ if ((commandParts.length > 1) && (commandParts.length != 2) ) {
108
+ throw errPrefix + (commandParts.length - 1).toString() + ' "?" delimiters found, expecting 1: "' + req.url + '"';
112
109
  }
113
110
 
114
111
 
115
112
 
116
- // if a query exists, split the query part [1] into name-value pairs on &, loop and construct a json result
113
+ // if a commandParts[1] (the parameters) exists, split the parameters into name-value pairs on &, loop and construct a json result
114
+ // the existance of a query part generates a dataObj, which determines whether a PUT or a GEt is used
117
115
  var dataObj;
118
- if (urlQueryParts.length > 1){
116
+ if (commandParts.length > 1){
119
117
  var result = '{';
120
118
  errPrefix = 'url query syntax error, ';
121
- urlQueryParts[1].split('&').forEach(function(nameValuePair) {
119
+ commandParts[1].split('&').forEach(function(nameValuePair) {
122
120
 
123
- //console.log('nameValuePair', nameValuePair );
121
+ //console.log('nameValuePair', nameValuePair );}
124
122
 
125
123
  const pair = nameValuePair.split('=');
126
124
  if (pair.length != 2){ throw errPrefix + (pair.length - 1).toString() + ' "=" delimiters found, expecting 1: "' + nameValuePair + '"';}
@@ -152,34 +150,45 @@ app.use('/api/' + options.username, (req, res) => {
152
150
  // PUT http://192.168.0.101/api/<username>/lights/31/state --data "{""on"":true}"
153
151
  var url = 'http://' + options.ip + '/api/' + options.username + '/' + resource;
154
152
  if (id) { url = url + '/' + id; } // add id if supplied
153
+
155
154
 
156
155
 
157
156
  // special handling for toggle command, this toggles a light or group state
157
+ // lights: http://localhost:3000/api/<username>/lights/31/toggle
158
+ // groups: http://localhost:3000/api/<username>/groups/0/toggle
159
+ // sensors: http://localhost:3000/api/<username>/sensors/15/toggle
158
160
  if (command == 'toggle') {
159
161
  console.log('toggling current state')
160
162
  // Get actual state
161
163
  console.log('sending GET: %s', url);
162
164
  axios.get(url)
163
165
  .then(response => {
164
- // for lights /lights/<id> state = on true/false
165
- // for groups, /groups/<id> state = all_on true/false
166
+ // for lights /lights/<id> state = on true/false
167
+ // for groups, /groups/<id> state = all_on true/false
168
+ // for sensors, /sensors/<id> config = on true/false
166
169
  switch(resource) {
167
170
  case 'lights':
168
171
  console.log('GET response:', response.status, response.statusText, "state:on="+response.data["state"]["on"] );
169
172
  state = !response.data["state"]["on"] // get the current on state , as a boolean, and invert it
170
- expectedCommand = 'state'
173
+ toggleCommand = 'state'
171
174
  break;
172
175
  case 'groups':
173
176
  console.log('GET response:', response.status, response.statusText, "state:all_on="+response.data["state"]["all_on"] );
174
177
  state = !response.data["state"]["all_on"] // get the current all_on state, as a boolean, and invert it
175
- expectedCommand = 'action'
178
+ toggleCommand = 'action'
179
+ break;
180
+ case 'sensors':
181
+ console.log('GET response:', response.status, response.statusText, "config:on="+response.data["config"]["on"] );
182
+ state = !response.data["config"]["on"] // get the current on state, as a boolean, and invert it
183
+ toggleCommand = 'config'
176
184
  break;
177
- }
185
+ }
178
186
  // 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
187
+ // lights: http://localhost:3000/api/<username>/lights/31/state?on=true
188
+ // groups: http://localhost:3000/api/<username>/groups/0/action?on=true
189
+ // sensors: http://localhost:3000/api/<username>/sensors/15/config?on=true
181
190
  console.log('sending PUT: %s%s', url + '/' + "state?on=", state.toString() || '');
182
- axios.put(url + '/' + expectedCommand,'{"on":' + state.toString() + '}')
191
+ axios.put(url + '/' + toggleCommand,'{"on":' + state.toString() + '}')
183
192
  .then(response => {
184
193
  console.log('PUT response:', response.status, response.statusText, JSON.stringify(response.data) );
185
194
  res.json(response.data);
@@ -200,8 +209,8 @@ app.use('/api/' + options.username, (req, res) => {
200
209
  // normal handling for non-toggle commands
201
210
  } else {
202
211
  if (dataObj){
203
- console.log('sending PUT: %s %s', url + '/' + expectedCommand, dataObj || '');
204
- axios.put(url + '/' + expectedCommand, dataObj)
212
+ console.log('sending PUT: %s %s', url + '/' + putCommand, dataObj || '');
213
+ axios.put(url + '/' + putCommand, dataObj)
205
214
  .then(response => {
206
215
  console.log('PUT response:', response.status, response.statusText, JSON.stringify(response.data) );
207
216
  res.json(response.data);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hueget",
3
- "version": "0.7.6",
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",
3
+ "version": "1.0.0",
4
+ "description": "A simple API that converts the Philips Hue API PUT to GET requests, allowing control of Philips Hue lights, groups, sensors and more via http GET requests",
5
5
  "main": "hueget.js",
6
6
  "scripts": {
7
7
  "test": "echo \"Error: no test specified\" && exit 1"