hueget 0.6.5 → 0.7.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 +7 -0
- package/README.md +31 -15
- package/hueget.js +69 -16
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@ 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.0 (2024-01-06)
|
|
8
|
+
* Added toggle capability for lights and groups
|
|
9
|
+
* Bumped dependencies: "axios": "^1.6.5"
|
|
10
|
+
|
|
11
|
+
## 0.6.6 (2023-11-27)
|
|
12
|
+
* Added some more README.md improvements
|
|
13
|
+
|
|
7
14
|
## 0.6.5 (2023-11-27)
|
|
8
15
|
* Added error handling to catch listener errors (e.g. port in use)
|
|
9
16
|
* Added some more README.md improvements
|
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
|
|
|
@@ -35,19 +38,20 @@ Flash lights in a room or in any group (zone, room) when someone comes home. The
|
|
|
35
38
|
# Installing hueget
|
|
36
39
|
I run hueget on my raspberry pi. To install the latest version with NPM:
|
|
37
40
|
```
|
|
38
|
-
$
|
|
41
|
+
$ npm install hueget
|
|
39
42
|
```
|
|
40
43
|
Or for the latest beta version:
|
|
41
44
|
```
|
|
42
|
-
$
|
|
45
|
+
$ npm install hueget@beta
|
|
43
46
|
```
|
|
44
47
|
|
|
45
|
-
|
|
48
|
+
You need to know where hueget was installed. Use `find -name hueget.js` to find the location of hueget.
|
|
49
|
+
I prefer to install locally. In my case, on my Raspberry Pi and using the default user pi, hueget installs in `/home/pi/node_modules/hueget/`
|
|
46
50
|
|
|
47
51
|
# Updating hueget
|
|
48
52
|
To update hueget to the latest version:
|
|
49
53
|
```
|
|
50
|
-
$
|
|
54
|
+
$ npm update hueget
|
|
51
55
|
```
|
|
52
56
|
|
|
53
57
|
|
|
@@ -56,11 +60,12 @@ The following examples assume you have hueget in a folder that your system can f
|
|
|
56
60
|
|
|
57
61
|
To see the help text, start hueget without any arguments as follows:
|
|
58
62
|
```
|
|
59
|
-
$ node /
|
|
63
|
+
$ node /home/pi/node_modules/hueget/hueget.js
|
|
60
64
|
```
|
|
61
65
|
|
|
62
66
|
hueget shows the following response:
|
|
63
67
|
```
|
|
68
|
+
Missing option: "--ip"
|
|
64
69
|
USAGE: node hueget.js [OPTION1] [OPTION2]... arg1 arg2...
|
|
65
70
|
The following options are supported:
|
|
66
71
|
-i, --ip <ARG1> Philips Hue bridge IP address (required)
|
|
@@ -71,15 +76,15 @@ Note that options can be entered in any order.
|
|
|
71
76
|
|
|
72
77
|
Example to run hueget on a raspberry pi to connect to a Philips Hue bridge with ip address `192.168.0.101`, default port `3000`, and with a Hue username of `UBxWZChHseyjeFwAkwgbdQ08x9XASWpanZZVg-mj`:
|
|
73
78
|
```
|
|
74
|
-
$ node /
|
|
79
|
+
$ node /home/pi/node_modules/hueget/hueget.js -i 192.168.0.101 -u UBxWZChHseyjeFwAkwgbdQ08x9XASWpanZZVg-mj
|
|
75
80
|
```
|
|
76
81
|
The same again, but using port `1234`:
|
|
77
82
|
```
|
|
78
|
-
$ node /
|
|
83
|
+
$ node /home/pi/node_modules/hueget/hueget.js -i 192.168.0.101 -u UBxWZChHseyjeFwAkwgbdQ08x9XASWpanZZVg-mj -p 1234
|
|
79
84
|
```
|
|
80
85
|
A successful start of hueget (using the above command to specify ip address 192.168.0.100 and port 1234) will show:
|
|
81
86
|
```
|
|
82
|
-
hueget v0.
|
|
87
|
+
hueget v0.7.0
|
|
83
88
|
commands will be sent to 192.168.0.101 with username UBxWZChHseyjeFwAkwgbdQ08x9XASWpanZZVg-mj
|
|
84
89
|
listening on port 1234
|
|
85
90
|
```
|
|
@@ -91,7 +96,7 @@ $ pm2 startup
|
|
|
91
96
|
|
|
92
97
|
To start hueget with pm2, and have it daemonized, monitored and kept alive forever:
|
|
93
98
|
```
|
|
94
|
-
$ pm2 start /
|
|
99
|
+
$ pm2 start /home/pi/node_modules/hueget/hueget.js -- -i 192.168.0.101 -u UBxWZChHseyjeFwAkwgbdQ08x9XASWpanZZVg-mj -p 3000
|
|
95
100
|
```
|
|
96
101
|
Check that hueget has started:
|
|
97
102
|
```
|
|
@@ -105,7 +110,7 @@ $ pm2 save
|
|
|
105
110
|
Managing hueget in pm2 is straightforward:
|
|
106
111
|
```
|
|
107
112
|
$ pm2 status
|
|
108
|
-
$ pm2 start /
|
|
113
|
+
$ pm2 start /home/pi/node_modules/hueget/hueget.js.js -- -i 192.168.0.101 -u UBxWZChHseyjeFwAkwgbdQ08x9XASWpanZZVg-mj -p 3000
|
|
109
114
|
$ pm2 save
|
|
110
115
|
$ pm2 stop hueget
|
|
111
116
|
$ pm2 restart hueget
|
|
@@ -142,6 +147,7 @@ Examples:
|
|
|
142
147
|
* Turn light 31 on at 50% brightness: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/31/state?on=true&bri=50
|
|
143
148
|
* Turn light 31 on at 100% brightness: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/31/state?on=true&bri=100
|
|
144
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
|
|
145
151
|
* Identify light 31 with a single blink: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/31/state?alert=select
|
|
146
152
|
* Identify light 31 with 15 seconds of blinking: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/lights/31/state?alert=lselect
|
|
147
153
|
|
|
@@ -149,12 +155,14 @@ Examples:
|
|
|
149
155
|
### Group 0 (a special group for all lights in your home)
|
|
150
156
|
* Turn group 0 on: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/0/action?on=true
|
|
151
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
|
|
152
159
|
* Identify group 0 with 15 seconds of blinking: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/0/action?alert=lselect
|
|
153
160
|
|
|
154
161
|
|
|
155
162
|
### Group 2 (example)
|
|
156
163
|
* Turn group 2 on: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2/action?on=true
|
|
157
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
|
|
158
166
|
* Turn group 2 on at 50% brightness: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2/action?on=true&bri=50
|
|
159
167
|
* Turn group 2 on at 100% brightness: http://192.168.0.101:3000/api/yourPhilipsHueBridgeUsername/groups/2/action?on=true&bri=100
|
|
160
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]
|
|
@@ -163,7 +171,15 @@ Examples:
|
|
|
163
171
|
|
|
164
172
|
Groups are collections of lights, and are used for Rooms and Zones in the Hue app.
|
|
165
173
|
|
|
166
|
-
|
|
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
|
|
167
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.
|
|
168
184
|
|
|
169
185
|
The full JSON response for a light looks like this:
|
|
@@ -176,12 +192,12 @@ The full JSON response for a group looks like this:
|
|
|
176
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"}}
|
|
177
193
|
```
|
|
178
194
|
The most common action keywords for state or group are:
|
|
179
|
-
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).
|
|
180
196
|
More keywords exist, see the [API documentation](#api-documentation).
|
|
181
197
|
|
|
182
198
|
## on (get and set)
|
|
183
199
|
Turn a light on or off. On=true, Off=false.
|
|
184
|
-
Valid for light or group.
|
|
200
|
+
Valid for light or group. A group also supports all_on and any_on.
|
|
185
201
|
|
|
186
202
|
## bri (get and set)
|
|
187
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).
|
|
@@ -245,7 +261,7 @@ See the [API documentation](#api-documentation).
|
|
|
245
261
|
|
|
246
262
|
## API Documentation
|
|
247
263
|
For full details of the control capabilities, please see the [official Philips Hue API reference](https://developers.meethue.com/develop/hue-api/).
|
|
248
|
-
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.
|
|
249
265
|
|
|
250
266
|
|
|
251
267
|
# Finding your Light or Group ids
|
|
@@ -263,6 +279,6 @@ Go backwards in the text until you find the keyword **state**, this is at the st
|
|
|
263
279
|
... ,"31":{"state":{"on":true,"bri":100,"hue":65396 ...
|
|
264
280
|
```
|
|
265
281
|
|
|
266
|
-
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.
|
|
267
283
|
|
|
268
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
|
-
|
|
100
|
-
if (
|
|
101
|
-
|
|
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
|
-
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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
|
-
|
|
155
|
-
|
|
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('
|
|
195
|
+
console.log('GET error:', errText);
|
|
160
196
|
res.json({ error: errText });
|
|
161
197
|
});
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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('
|
|
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('
|
|
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.
|
|
3
|
+
"version": "0.7.0",
|
|
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,7 +25,7 @@
|
|
|
25
25
|
"author": "Jochen Siegenthaler (https://github.com/jsiegenthaler)",
|
|
26
26
|
"license": "ISC",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"axios": "^1.6.
|
|
28
|
+
"axios": "^1.6.5",
|
|
29
29
|
"express": "^4.18.2",
|
|
30
30
|
"stdio": "^2.1.1"
|
|
31
31
|
},
|