맹주환

Add node_hue_api file

Showing 1000 changed files with 4840 additions and 0 deletions

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +# Capabilities API
2 +
3 +The `capabilities` API provides a means of obtaining the capabilities of the Bridge, along with totals as to how
4 +many more things of each type can be stored/created.
5 +
6 +
7 +* [getAll()](#getAll)
8 +* [Capabilities Object](#capabilities-object)
9 + * [lights](#lights)
10 + * [sensors](#sensors)
11 + * [groups](#groups)
12 + * [scenes](#scenes)
13 + * [schedules](#schedules)
14 + * [rules](#rules)
15 + * [resourcelinks](#resourcelinks)
16 + * [streaming](#streaming)
17 + * [timezones](#timezones)
18 +
19 +
20 +## getAll
21 +The `getAll()` function will get the complete capabilities from the Hue Bridge.
22 +
23 +```js
24 +api.capabilities.getAll()
25 + .then(capabilities => {
26 + // Display the full capabilities from the bridge
27 + console.log(capabilities.toStringDetailed());
28 + })
29 +;
30 +```
31 +
32 +The function call will resolve to a `Capabilities` Object.
33 +
34 +A complete code sample is available [here](../examples/v3/capabilities/getAllCapabilities.js).
35 +
36 +
37 +## Capabilities Object
38 +
39 +The Capabilities Object is an object that holds all the capability data obtained from the bridge.
40 +The properties available on this object are detailed below:
41 +
42 +### lights
43 +Obtains the capabilities for the total number of supported lights on the bridge and how many more can be added.
44 +
45 +* `get`
46 +
47 +```js
48 +{
49 + "available": 23,
50 + "total": 63
51 +}
52 +```
53 +
54 +### sensors
55 +Obtains the capabilities for the total number of supported sensors on the bridge and how many more can be added.
56 +It has a further break down on the supported types of sensors, `clip`, `zll` and `zgp`.
57 +
58 +* `get`
59 +
60 +```js
61 +{
62 + "available": 209,
63 + "total": 250,
64 + "clip": {
65 + "available": 209,
66 + "total": 250
67 + },
68 + "zll": {
69 + "available": 62,
70 + "total": 64
71 + },
72 + "zgp": {
73 + "available": 62,
74 + "total": 64
75 + }
76 +}
77 +```
78 +
79 +### groups
80 +Obtains the capabilities for the total number of supported groups on the bridge and how many more can be added.
81 +
82 +* `get`
83 +
84 +```js
85 +{
86 + "available": 41,
87 + "total": 64
88 +}
89 +```
90 +
91 +### scenes
92 +Obtains the capabilities for the total number of supported scenes on the bridge and how many more can be added.
93 +It also details how many more lightstates are in use and how many more can be created.
94 +
95 +* `get`
96 +
97 +```js
98 +{
99 + "available": 89,
100 + "total": 200,
101 + "lightstates": {
102 + "available": 5210,
103 + "total": 12600
104 + }
105 +}
106 +```
107 +
108 +### schedules
109 +Obtains the capabilities for the total number of supported schedules on the bridge and how many more can be added.
110 +
111 +* `get`
112 +
113 +```js
114 +{
115 + "available": 97,
116 + "total": 100
117 +}
118 +```
119 +
120 +### rules
121 +Obtains the capabilities for the total number of supported rules on the bridge and how many more can be added.
122 +It also contains similar breakdowns for the `conditions` and the `actions`.
123 +* `get`
124 +
125 +```js
126 +{
127 + "available": 218,
128 + "total": 250,
129 + "conditions": {
130 + "available": 1429,
131 + "total": 1500
132 + },
133 + "actions": {
134 + "available": 956,
135 + "total": 1000
136 + }
137 +```
138 +
139 +### resourcelinks
140 +Obtains the capabilities for the total number of supported schedules on the bridge and how many more can be added.
141 +
142 +This is also available as `resourceLinks` getter on the Object (which is consistent with naming of ResourceLinks elsewhere in the API),
143 +
144 +* `get`
145 +
146 +```js
147 +{
148 + "available": 51,
149 + "total": 64
150 +}
151 +```
152 +
153 +### streaming
154 +Obtains the capabilities for around the Entertainment streaming functions.
155 +
156 +* `get`
157 +
158 +```js
159 +{
160 + "available": 1,
161 + "total": 1,
162 + "channels": 10
163 +}
164 +```
165 +
166 +### timezones
167 +Obtains a list of the timezones known to the Hue Bridge as an Array of `String`s.
168 +
169 +* `get`
...\ No newline at end of file ...\ No newline at end of file
1 +# Configuration API
2 +
3 +The `configuration` API provides a means of interacting with the Hue Bridge configuration. Some of these options do not
4 +require you to have an existing user, as in the creation of a new user account, but most of them do.
5 +
6 +
7 +* [getAll()](#getAll)
8 +* [get()](#get)
9 +* [update(data)](#update)
10 +* [pressLinkButton()](#pressLinkButton)
11 +
12 +
13 +
14 +## getAll
15 +The `getAll()` function will get the complete configuration and states from the
16 +Hue Bridge.
17 +
18 +This includes the bridge configuration and a number of other items:
19 +
20 +* `lights`: JSON representation of the Lights in the bridge
21 +* `sensors`: JSON representation of the Sensors in the bridge
22 +* `rules`: JSON representation of all the Rules in the bridge
23 +* `schedules`: JSON representation of the Schedules in the bridge
24 +* `resourcelinks`: Resource links used by the Bridge
25 +* `config`: The configuration of the bridge.
26 +
27 +```js
28 +api.configuration.getAll()
29 + .then(config => {
30 + // Display the full configuration from the bridge
31 + console.log(JSON.stringify(config, null, 2));
32 + })
33 +;
34 +```
35 +
36 +A complete code sample is available [here](../examples/v3/configuration/getAllConfiguration.js).
37 +
38 +
39 +
40 +## get
41 +The `get()` function will obtain just the configuration of the Hue Bridge.
42 +
43 +The result will be an `Object` with all the configuration options of the Bridge. These change depending upon
44 +the software version of the bridge.
45 +
46 +```js
47 +api.configuration.get()
48 + .then(config => {
49 + // Display the configuration from the bridge
50 + console.log(JSON.stringify(config, null, 2));
51 + })
52 +;
53 +```
54 +
55 +A complete code sample is available [here](../examples/v3/configuration/getConfiguration.js).
56 +
57 +
58 +
59 +## update
60 +The `update(data)` function will attempt to update the specified configuration on
61 +the Hue Bridge.
62 +
63 +The data parameter is a key value `Object` that contains the keys and associated
64 +values that you wish to set in the Bridge configuration.
65 +
66 +To get an up to date list of options (some of which may not be modifiable), check
67 +the result from the `get()` function, as these values change over time when the
68 +Hue Bridge is updated.
69 +
70 +If you attempt to set an unmodifiable option, then an `ApiError` will be generated.
71 +
72 +```js
73 +api.configuration.update({proxyport: 8080})
74 + .then(result => {
75 + console.log(`Updated proxy port? ${result}`);
76 + })
77 +;
78 +```
79 +
80 +The function call will resolve with a `Boolean` indicating the success status.
81 +
82 +A complete code sample is available [here](../examples/v3/configuration/update.js).
83 +
84 +
85 +
86 +## pressLinkButton
87 +The `pressLinkButton()` function is an older API call, in later versions the Hue Bridge has disabled the ability
88 +to modify this value via the `configuration` API.
89 +
90 +This used to be a way to virtually press the link button. Now for security, you have to actually press the link button on
91 +the Bridge.
...\ No newline at end of file ...\ No newline at end of file
1 +# Discovery
2 +
3 +There are two ways to discover a Hue bridge on the network using N-UPnP and UPnP methods. Both of these methods are
4 +useful if you do not know the IP Address of the bridge already.
5 +
6 +The official Hue documentation recommends an approach to finding bridges by using both UPnP and N-UPnP in parallel
7 +to find your bridges on the network. This API library provided you with both options, but leaves it
8 +to the developer to decide on the approach to be used, i.e. fallback, parallel, or just one type.
9 +
10 +
11 +- [N-UPnP Search](#n-upnpsearch)
12 +- [UPnP Search](#upnp-search)
13 +
14 +
15 +## N-UPnP Search
16 +This API function makes use of the official API endpoint that reveals the bridges on a network. It is a call through to
17 +`https://discovery.meethue.com` which may not work in all circumstances (your bridge must have signed into the meethue portal),
18 +in which case you can fall back to the slower ``upnpSearch()`` function.
19 +
20 +_Note: This function is considerably faster to resolve the bridges < 500ms compared to 5 seconds to perform a full
21 +search via UPnP on my own network._
22 +
23 +```js
24 +const v3 = require('node-hue-api').v3;
25 +
26 +async function getBridge() {
27 + const results = await v3.discovery.nupnpSearch();
28 +
29 + // Results will be an array of bridges that were found
30 + console.log(JSON.stringify(results, null, 2));
31 +}
32 +
33 +getBridge();
34 +```
35 +
36 +The results will be an array of valid discovered bridges with the following structure:
37 +
38 +```json
39 +[
40 + {
41 + "name": "Philips hue",
42 + "ipaddress": "192.xxx.xxx.xxx",
43 + "modelid": "BSB002",
44 + "swversion": "1935074050"
45 + }
46 +]
47 +```
48 +
49 +If a bridge is registered in the Hue portal and returned from the discovery endpoint that is queried but cannot be
50 +connected to for any reason (i.e. it is offline), then the bridge data will be provided in an error object of the form:
51 +
52 +```json
53 +{
54 + "error": {
55 + "message": "An error message",
56 + "description": "Failed to connect and load configuration from the bridge at ip address xxx.xxx.xxx.xxx",
57 + "ipaddress": "xxx.xxx.xxx.xxx",
58 + "id": "xxxxxxxxxxxxxxxx"
59 + }
60 +}
61 +```
62 + The `message` value will be that of the underlying error when attempting to resolve the bridge configuration. The `id`
63 + is the mac address reported from the discovery portal and the `ipaddress` is that of the recorded ip address from the
64 + discovery portal.
65 +
66 +
67 +## UPnP Search
68 +
69 +This API function utilizes a network scan for the SSDP responses of devices on a network. This ius a significantly slower
70 +way to find the Bridge, but can be useful if you have not set it up yet and it has not registered with the meethue portal.
71 +
72 +Note that you must be on the same network as the bridge for this to work.
73 +
74 +```js
75 +const v3 = require('node-hue-api').v3;
76 +
77 +async function getBridge(timeout) {
78 + const results = await v3.discovery.upnpSearch(timeout);
79 +
80 + // Results will be an array of bridges that were found
81 + console.log(JSON.stringify(results, null, 2));
82 +}
83 +
84 +// You can pass a timeout value to set the maximum time to search for Hue Bridges, there is a default of 5 seconds if not set
85 +getBridge(10000); // 10 second timeout
86 +```
87 +
88 +
89 +A timeout can be provided to the function to increase/decrease the amount of time that it waits for responses from the
90 +search request, by default this is set to 5 seconds (the above example sets this to 10 seconds).
91 +
92 +The results from this function call will be of the form;
93 +
94 +```json
95 +[
96 + {
97 + "name": "Philips hue (192.xxx.xxx.xxx)",
98 + "manufacturer": "Royal Philips Electronics",
99 + "ipaddress": "192.xxx.xxx.xxx",
100 + "model": {
101 + "number": "BSB002",
102 + "description": "Philips hue Personal Wireless Lighting",
103 + "name": "Philips hue bridge 2015",
104 + "serial": "0017xxxxxxxx"
105 + },
106 + "version": {
107 + "major": "1",
108 + "minor": "0"
109 + },
110 + "icons": [
111 + {
112 + "mimetype": "image/png",
113 + "height": "48",
114 + "width": "48",
115 + "depth": "24",
116 + "url": "hue_logo_0.png"
117 + }
118 + ]
119 + }
120 +]
121 +```
...\ No newline at end of file ...\ No newline at end of file
1 +# Group
2 +
3 +A `Group` is a representation of a grouping construct in the Hue Bridge, of which there are a number of specializations
4 +including serrving different purposes:
5 +
6 +* [`LightGroup`](#lightgroup): The default type of Group which collects lights and sensors
7 +* [`Luminaire`](#luminaire): A special type of group representing a Luminaire, the bridge will create these for these devices if you have any
8 +* [`Room`](#room): A Room that collects a number of lights and sensors togehter (a light and sensor can only belong to a single `Room`)
9 +* [`Entertainment`](#entertainment): A new special type of Group used for an Entertainment area for streaming (syncing light changes
10 + to a visualization via a seperate streaming API). Not all lights can be added to an Entertainment Group.
11 +* [`Zone`](#zone): A group that allows you to define a Zone that might be within a room, or extend across a number of rooms.
12 + This allows you to work around the `Room` limitations of lights and sensors only being able to belong to one Room.
13 +
14 +You cannot create these Object directly, but can either retrieve them from the Hue Bridge via the [Groups API](./groups.md)
15 +or create a new instance of them using the `v3.model` functions:
16 +
17 +* `v3.model.createLightGroup()`
18 +* `v3.model.createRoom()`
19 +* `v3.model.createZone()`
20 +* `v3.model.createEntertainment()`
21 +
22 +
23 +* [Common Group Properties and Functions](#common-group-properties-and-functions)
24 + * [id](#id)
25 + * [name](#name)
26 + * [lights](#lights)
27 + * [type](#type)
28 + * [action](#action)
29 + * [recycle](#recycle)
30 + * [sensors](#sensors)
31 + * [state](#state)
32 + * [toString()](#tostring)
33 + * [toStringDetailed()](#tostringdetailed)
34 +* [LightGroup](#lightgroup)
35 +* [Room](#room)
36 + * [class](#class)
37 +* [Zone](#zone)
38 + * [class](#class
39 +* [Entertainment](#entertainment)
40 + * [class](#class)
41 + * [locations](#locations)
42 + * [stream](#stream)
43 +
44 +
45 +
46 +## Common Group Properties and Functions
47 +
48 +The properties and functions available for all `Group`s are:
49 +
50 +## id
51 +The id for the group.
52 +
53 +* `get`
54 +
55 +
56 +## name
57 +The name for the group.
58 +
59 +* `get`
60 +* `set`
61 +
62 +
63 +## lights
64 +An array of light `id`s that are in the group
65 +
66 +* `get`
67 +
68 +
69 +## type
70 +The type of group that this `Group` instance represents.
71 +
72 +* `get`
73 +
74 +The type can be one of the following values:
75 +
76 +* `Lunimarie`: Multisource Luminaire group
77 +* `Lighsource`: Multisource Luminaire group
78 +* `LightGroup`: A group of lights that can be controlled together
79 + * A light group is deleted by the bridge if you remove all the lights from it
80 +* `Room`
81 +* `Entertainment`
82 +* `Zone`
83 +
84 +
85 +## action
86 +The Light state of one of the lamps in the group.
87 +
88 +* `get`
89 +
90 +
91 +## recycle
92 +A flag indicating if the bridge can automatically remove the group.
93 +
94 +* `get`
95 +
96 +
97 +## sensors
98 +An `Array` of sensor `id`s that are associated with the group, which can be empty.
99 +
100 +* `get`
101 +
102 +
103 +## state
104 +A state representation of the group. Which can contain details like `all_on` or `any_on` which indicate if all or any of
105 +the light members are currently on.
106 +
107 +`get`
108 +
109 +
110 +### toString()
111 +The `toString()` function will obtain a simple `String` representation of the Scene.
112 +
113 +
114 +### toStringDetailed()
115 +The `toStringDetailed()` function will obtain a more detailed representation of the Scene object.
116 +
117 +
118 +
119 +## LightGroup
120 +
121 +The standard LightGroup has all the properties and functions defined in the [common group properties](#common-group-properties-and-functions).
122 +
123 +
124 +## Room
125 +A group of lights that are physically located in the same place in a house. These behave like a standard group, but have a couple of differences:
126 +
127 +* A room can be empty and contain no lights
128 +* A light is only allowed in a single room
129 +* A room is not automatically deleted when all the lights are removed
130 +
131 +The `Room` Group has all the properties and functions as defined in the [common group properties](#common-group-properties-and-functions)
132 +as well as the following:
133 +
134 +## class
135 +The `class` represents the `Zone` category as a `String`.
136 +
137 +* `get`
138 +* `set`
139 +
140 +The values that can be set for this on a `Room` are:
141 +
142 +-------------- | -------------- | ----------
143 +`Living room` | `Kitchen` | `Dining`
144 +`Bedroom` | `Kids bedroom` | `Bathroom`
145 +`Nursery` | `Recreation` | `Office`
146 +`Gym` | `Hallway` | `Toilet`
147 +`Front door` | `Garage` | `Terrace`
148 +`Garden` | `Driveway` | `Carport`
149 +`Other` | |
150 +
151 +Since version 1.30 of the Hue Bridge API the following values can also be used:
152 +
153 +-------------- | ------------- | ----------
154 +`Home` | `Downstairs` | `Upstairs`
155 +`Top floor` | `Attic` | `Guest room`
156 +`Staircase` | `Lounge` | `Man cave`
157 +`Computer` | `Studio` | `Music`
158 +`TV` | `Reading` | `Closet`
159 +`Storage` | `Laundry room` | `Balcony`
160 +`Porch` | `Barbecue` | `Pool`
161 +
162 +
163 +## Zone
164 +A group of lights that can be controlled together.
165 +
166 +* A zone can be empty and contain no lights
167 +* A light is allowed to be in multiple zones (as opposed to only being able to belong to a single room)
168 +
169 +The `Zone` Group has all the properties and functions as defined in the [common group properties](#common-group-properties-and-functions)
170 +as well as the following:
171 +
172 +## class
173 +The `class` represents the `Zone` category as a `String`.
174 +
175 +* `get`
176 +* `set`
177 +
178 +The values that can be set for this on a `Room` are:
179 +
180 +-------------- | -------------- | ----------
181 +`Living room` | `Kitchen` | `Dining`
182 +`Bedroom` | `Kids bedroom` | `Bathroom`
183 +`Nursery` | `Recreation` | `Office`
184 +`Gym` | `Hallway` | `Toilet`
185 +`Front door` | `Garage` | `Terrace`
186 +`Garden` | `Driveway` | `Carport`
187 +`Other` | |
188 +
189 +Since version 1.30 of the Hue Bridge API the following values can also be used:
190 +
191 +-------------- | ------------- | ----------
192 +`Home` | `Downstairs` | `Upstairs`
193 +`Top floor` | `Attic` | `Guest room`
194 +`Staircase` | `Lounge` | `Man cave`
195 +`Computer` | `Studio` | `Music`
196 +`TV` | `Reading` | `Closet`
197 +`Storage` | `Laundry room` | `Balcony`
198 +`Porch` | `Barbecue` | `Pool`
199 +
200 +
201 +
202 +## Entertainment
203 +Represents an entertainment set up, which is a group of lights used to define targets for streaming along with defining position of the lights.
204 +
205 +The Entertainment Group has all the properties and functions as defined in the [common group properties](#common-group-properties-and-functions)
206 +as well as the following:
207 +
208 +* [class](#class)
209 +* [locations](#locations)
210 +* [stream](#stream)
211 +
212 +## class
213 +The `class` represents the `Entertainment` category as a `String`.
214 +
215 +* `get`
216 +
217 +The values that can be set for this on a are:
218 +
219 +* `TV`
220 +* `Other`
221 +
222 +
223 +## locations
224 +The locations of the lights in an `Entertainment` type Group which is an Object that maps the `id` of the light to an
225 +`Array` consisting of three integers inidicating the position in 3D space from the source.
226 +
227 +`get`
228 +
229 +
230 +## stream
231 +The stream details object for an `Entertainment` type Group.
232 +
233 +`get`
234 +
235 +The stream object consists of the following keys and values:
236 +
237 +* `proxymode`: A string indicating the proxy mode
238 +* `proxynode`: A string which is an address string to a light in the bridge, e.g. `/lights/22`
239 +* `active`: A Boolean indicating whether or not the Entertainment is currently streaming
240 +* `owner`: If the Entertainment is currently streaming, this is the user id of the owner of the stream.
1 +# Groups API
2 +
3 +The `groups` API provides a means of interacting with groups in the Hue Bridge.
4 +
5 +* [getAll()](#getall)
6 +* [getGroup()](#getgroup)
7 +* [getGroupByName()](#getgroupbyname)
8 +* [get by type](#get-by-type)
9 +* [createGroup()](#creategroup)
10 +* [updateGroupAttributes()](#updategroupattributes)
11 +* [deleteGroup()](#deletegroup)
12 +* [getGroupState()](#getgroupstate)
13 +* [setGroupState()](#setgroupstate)
14 + * [Activating a Scene](#activating-a-scene)
15 +
16 +
17 +
18 +## getAll()
19 +The `getAll()` function allows you to get all the groups that the Hue Bridge has defined.
20 +
21 +```js
22 +api.groups.getAll()
23 + .then(allGroups => {
24 + // Display the groups from the bridge
25 + allGroups.forEach(group => {
26 + console.log(group.toStringDetailed());
27 + });
28 + });
29 +```
30 +
31 +This function call will resolve to an `Array` of `Group` instance objects (LightGroup, Zone, Room, Entertainment and Luminaire,
32 +see [Group Objects](./group.md) for more details).
33 +
34 +A complete code sample for this function is available [here](../examples/v3/groups/getAllGroups.js).
35 +
36 +
37 +
38 +## getGroup()
39 +The `getGroup(id)` function will allow to to get the group specified by the `id` value.
40 +
41 +* `id`: The integer `id` of the group you wish to retrieve, or a `Group` object that you want a refreshed copy of.
42 +
43 +```js
44 +api.groups.getGroup(1)
45 + .then(group => {
46 + console.log(group.toStringDetailed());
47 + })
48 +;
49 +```
50 +
51 +The call will resolve to a [`Group Object`](./group.md) instance for the specified `id`.
52 +
53 +A complete code sample for this function is available [here](../examples/v3/groups/getGroup.js).
54 +
55 +
56 +
57 +## getGroupByName()
58 +The `getGroupByName(name)` function will retrieve the group(s) from the Hue Bridge that have the specified `name`. Group names
59 +are not guaranteed to be unique in the Hue Bridge.
60 +
61 +```js
62 +api.groups.getGroupByName('myGroup')
63 + .then(matchedGroups => {
64 + // Display the groups from the bridge
65 + matchedGroups.forEach(group => {
66 + console.log(group.toStringDetailed());
67 + });
68 + });
69 +```
70 +
71 +The call will resolve to an `Array` of `Group Objects`](./group.md) that have a matching `name`.
72 +
73 +A complete code sample for this function is available [here](../examples/v3/groups/getGroupByName.js).
74 +
75 +
76 +
77 +## get by type
78 +
79 +You can retrieve a specific `type` of `Group` from the Hue Bridge using the following functions:
80 +
81 +* `getLightGroups()`
82 +* `getLuminaires()`
83 +* `getLightSources()`
84 +* `getRooms()`
85 +* `getZones()`
86 +* `getEntertainment()`
87 +
88 +For example to get all the `zone` Groups from the Hue Bridge:
89 +```js
90 +api.groups.getZones()
91 + .then(zones => {
92 + // Do something with the zone groups.
93 + console.log(`There are ${zones.length} defined zones in the bridge`);
94 + })
95 +;
96 +```
97 +
98 +All these functions will resolve to an `Array` of matching [Group Objects](./group.md) that matches the `type` that was requested; e.g. a Zones if you call `getZones()`.
99 +
100 +A complete code samples for these functions is available [here](../examples/v3/groups/getGroupByType.js).
101 +
102 +
103 +
104 +## createGroup()
105 +The `createGroup(group)` function allows you to create an instance of a specific [`Group Object`](./group.md) in the Hue Bridge.
106 +
107 +* `group`: The Group object that has been built that you wish to create, e.g. a LightGroup populated with a name and light ids
108 +
109 +```js
110 +const group = v3.model.createLightGroup();
111 +group.name = 'my new group';
112 +group.lights = [2, 3];
113 +
114 +api.groups.createGroup(group)
115 + .then(createdGroup => {
116 + console.log(`Created new group:\n${createdGroup.toStringDetailed()});
117 + })
118 +;
119 +```
120 +
121 +The call will resolve to a [`Group Object`](./group.md) that was created using the provided details.
122 +
123 +Complete code samples creating various types of Groups are available:
124 +* [LightGroup](../examples/v3/groups/createLightGroup.js)
125 +* [Room](../examples/v3/groups/createRoom.js)
126 +* [Zone](../examples/v3/groups/createZone.js)
127 +* [Entertainment](../examples/v3/groups/createEntertainment.js)
128 +
129 +
130 +
131 +## updateGroupAttributes()
132 +The `updateGroupAttributes(group)` function allows you to update the attributes of an existing group. The attributes that
133 +can be modified are:
134 +
135 + * `name`
136 + * `lights`
137 + * `sensors`
138 + * `class`: The class for the Room/Zone or Entertainment Group
139 +
140 +* `group`: The Group that has been modified with the updates you want to apply to the Bridge Group.
141 +
142 +```js
143 +const group; // Obtained from some other call to retrieve this reference to a Group object from the bridge
144 +// Update the name
145 +group.name = 'Updated Group Name';
146 +
147 +api.groups.updateGroupAttributes(group)
148 + .then(result => {
149 + console.log(`Updated attributes: ${result}`)
150 + })
151 +;
152 +```
153 +
154 +The call will resolve to a `Boolean` indicating the success status of the update to the specified attributes.
155 +
156 +A complete code sample for this function is available [here](../examples/v3/groups/updateGroupAttributes.js).
157 +
158 +
159 +
160 +## deleteGroup()
161 +The `deleteGroup(id)` function allow you to delete a group from the Hue Bridge.
162 +
163 +* `id`: The integer `id` of the group to delete, or a `Group Object` that you wish to remove
164 +
165 +```js
166 +api.groups.deleteGroup(id)
167 + .then(result => {
168 + console.log(`Deleted group? ${result}`);
169 + })
170 +;
171 +```
172 +
173 +The call will resolve to a `Boolean` indicating the success status of the deletion.
174 +
175 +A complete code sample for this function is available [here](../examples/v3/groups/deleteGroup.js).
176 +
177 +
178 +
179 +## getGroupState()
180 +The `getGroupState(id)` function allows you to get the current state that has been applied to the `Group`.
181 +
182 +* `id`: The id of the group to get the state for, or Group Object.
183 +
184 +```js
185 +api.groups.getGroupState(id)
186 + .then(state => {
187 + // Display the current state
188 + console.log(JSON.stringify(state, null, 2));
189 + })
190 +;
191 +```
192 +
193 +The call will resolve to an `Object` that contains the current state values for the `Group`
194 +
195 +
196 +
197 +## setGroupState()
198 +The `setGroupState(id, state)` function allows you to set a state on the lights in the specified `Group`.
199 +
200 +* `id`: The id of the group to modify the state on, or a `Group Object`.
201 +* `state`: A `GroupLightState` for the group to be applied to the lights in the group. This can be an Object with explicit
202 + key values or a `GroupLightState` Object.
203 +
204 +
205 +Using an Object for the state, which must conform to the various state attributes that can be set for a `Group`:
206 +```js
207 +api.groups.setGroupState(groupId, {on: true})
208 + .then(result => {
209 + console.log(`Updated Group State: ${result}`);
210 + })
211 +;
212 +```
213 +
214 +
215 +Using a [`GroupLightState`](lightState.md#grouplightstate) Object:
216 +```js
217 +const GroupLightState = require('node-hue-api').v3.model.lightStates.GroupLightState;
218 +const groupState = new GroupLightState().on();
219 +
220 +api.groups.setGroupState(groupId, groupState)
221 + .then(result => {
222 + console.log(`Updated Group State: ${result}`);
223 + })
224 +;
225 +```
226 +
227 +The call will resolve to a `Boolean` indicating success state of setting the desired group light state.
228 +
229 +A complete code sample for this function is available [here](../examples/v3/groups/setGroupLightState.js).
230 +
231 +
232 +### Activating a Scene
233 +The `setGroupState(id, state)` function (as detailed above) is the function that needs to be used to activate/recall an
234 +existing `Scene` that is stored in the Hue Bridge / Lights.
235 +
236 +The lights that are affected by the Scene activation is the intersection of the members of the `Group` and the lights
237 +that were `Scene` associated with it.
238 +
239 +This means you can potentially target a single room/zone when recalling a Scene that might straddle multiple rooms or zones
240 +by limiting the target `Group` when recalling the Scene.
241 +
242 +So to ensure that you target all the lights that you associated with a `Scene`, when activating it, you would need to
243 +utilize the special `All Lights Group` which has an id of `0`.
244 +
245 +Example for recalling a Scene using the `All Lights Group`, that is all lights saved in the scene will be activated:
246 +```js
247 +const GroupLightState = require('node-hue-api').v3.lightStates.GroupLightState;
248 +const mySceneLightState = new GroupLightState().scene('my-scene-id');
249 +
250 +api.groups.setGroupState(0, mySceneLightState)
251 + .then(result => {
252 + console.log(`Activated Scene? ${result}`);
253 + })
254 +;
255 +```
256 +
257 +_Note: There is a convenience function on the Scenes API [activateScene(id)](./scenes.md#activatescene) that is a
258 +wrapper around the `setGroupState()` API call targeting the `All Lights Group`._
259 +
260 +
1 +# Light
2 +
3 +All Lights on the Bridge are built into a `Light` instance.
4 +
5 +The Hue Bridge has multiple types of lights which are:
6 +
7 +* `On Off Light`
8 +* `Dimmable Light`
9 +* `Color Light`
10 +* `Color Temperature Light`
11 +* `Extended Color Light`
12 +
13 +Each instance of a `Light` will have different properties depending upon their capabilities of the underlying type.
14 +
15 +
16 +
17 +
18 +
19 +* [Light Properties and Functions](#light-properties-and-functions)
20 + * [id](#id)
21 + * [name](#name)
22 + * [type](#type)
23 + * [modelid](#modelid)
24 + * [manufacturername](#manufacturername)
25 + * [uniqueid](#uniqueid)
26 + * [productid](#productid)
27 + * [swversion](#swversion)
28 + * [swupdate](#swupdate)
29 + * [state](#state)
30 + * [capabilities](#capabilites)
31 + * [coloeGamut](#colorgamut)
32 + * [getSupportedStates()](#getsupportedstates)
33 + * [toString()](#tostring)
34 + * [toStringDetailed()](#tostringdetailed)
35 +
36 +
37 +
38 +## Light Properties and Functions
39 +
40 +
41 +## id
42 +The id for the light in the Bridge.
43 +
44 +* `get`
45 +
46 +
47 +## name
48 +The name for the light.
49 +
50 +* `get`
51 +* `set`
52 +
53 +## type
54 +The type of the light.
55 +
56 +* `get`
57 +
58 +The known types of Lights (there may be more, and also variant of the strings):
59 +
60 + * `On Off Light`
61 + * `Dimmable Light`
62 + * `Color Light`
63 + * `Color Temperature Light`
64 + * `Extended Color Light`
65 +
66 +
67 +## modelid
68 +The model id of the light
69 +
70 +* `get`
71 +
72 +## manufacturername
73 +The manufacturer name of the light.
74 +
75 +* `get`
76 +
77 +## uniqueid
78 +The unique id of the light in the Hue Bridge.
79 +
80 +* `get`
81 +
82 +## productid
83 +The product id for the light
84 +
85 +* `get`
86 +
87 +## swversion
88 +The software version number, if applicable for the light.
89 +
90 +* `get`
91 +
92 +## swupdate
93 +The software update object for the light.
94 +
95 +* `get`
96 +
97 +The Object if present for a light (not all support software updates) is of the form:
98 +
99 +For a light that can be software updated:
100 +```json
101 +{
102 + "state": "noupdates",
103 + "lastinstall": "2019-09-23T22:12:54"
104 +}
105 +```
106 +
107 +For a light that does not support software updates:
108 +```json
109 +{
110 + "state": "notupdatable",
111 + "lastinstall": null
112 +}
113 +```
114 +
115 +## state
116 +The state of the light when it was retrieved from the Hue Bridge.
117 +
118 +* `get`
119 +
120 +This is an Object representation of a LightState, but is left as a raw Object.
121 +
122 +
123 +## capabilites
124 +An Object representing all the capabilities of the Light. The details for the capabilities varies depending upon the
125 +Light product and manufacturer. Older lights may report nothing whereas new Hue lights used for Entertainment Streaming
126 +will report a lot of details in their capabilities.
127 +
128 +* `get`
129 +
130 +An example of an Extended Color Light capabilities:
131 +```json
132 +"capabilities": {
133 + "certified": true,
134 + "control": {
135 + "mindimlevel": 5000,
136 + "maxlumen": 250,
137 + "colorgamuttype": "B",
138 + "colorgamut": [
139 + [
140 + 0.675,
141 + 0.322
142 + ],
143 + [
144 + 0.409,
145 + 0.518
146 + ],
147 + [
148 + 0.167,
149 + 0.04
150 + ]
151 + ],
152 + "ct": {
153 + "min": 153,
154 + "max": 500
155 + }
156 + },
157 + "streaming": {
158 + "renderer": true,
159 + "proxy": true
160 + }
161 +}
162 +```
163 +
164 +## colorGamut
165 +Obtains the matched Color Gamut for the Light. This can be loaded from the Light capabilities object, or
166 +via a matching against the light modelid.
167 +
168 +Only lights that support color will report a colorGamut (white lights will not have a color gamut).
169 +
170 +* `get`
171 +
172 +The result will either be `null` or an Object consisting of `red`, `green` and `blue` keys set to an Object with `x`, `y` values:
173 +
174 +```js
175 +{
176 + red: {x: 0.692, y: 0.308},
177 + green: {x: 0.17, y: 0.7},
178 + blue: {x: 0.153, y: 0.048}
179 +}
180 +```
181 +
182 +
183 +## getSupportedStates()
184 +The function `getSupportedStates()` will return an `Array` of `String` values that are the known states that can be set
185 +on the light.
186 +
187 +Typically you would not need to use this, as the `LightState` object would be used to set the LightState on a Light in
188 +the API, but this can be used to help limit the setting that you can build into a LightState in a UI, or
189 +programmatically.
190 +
191 +An example of this for an Extended Color Light is:
192 +```js
193 +[
194 + "on",
195 + "bri",
196 + "hue",
197 + "sat",
198 + "effect",
199 + "xy",
200 + "ct",
201 + "alert",
202 + "colormode",
203 + "mode",
204 + "reachable",
205 + "transitiontime",
206 + "bri_inc",
207 + "sat_inc",
208 + "hue_inc",
209 + "ct_inc",
210 + "xy_inc"
211 +]
212 +```
213 +
214 +An example for a Dimmable Light is:
215 +```js
216 +[
217 + "on",
218 + "bri",
219 + "alert",
220 + "mode",
221 + "reachable",
222 + "transitiontime",
223 + "bri_inc"
224 +]
225 +```
226 +
227 +## toString()
228 +The `toString()` function will obtain a simple `String` representation of the Light.
229 +
230 +e.g.
231 +```text
232 +Light
233 + id: 10
234 +```
235 +
236 +## toStringDetailed()
237 +The `toStringDetailed()` function will obtain a more detailed representation of the Light object.
238 +
239 +e.g.
240 +```text
241 +Light
242 + id: 14
243 + state: {"on":false,"bri":254,"alert":"select","mode":"homeautomation","reachable":false}
244 + swupdate: {"state":"noupdates","lastinstall":"2018-12-13T20:43:31"}
245 + type: "Dimmable light"
246 + name: "Hallway Entrance"
247 + modelid: "LWB004"
248 + manufacturername: "Philips"
249 + productname: "Hue white lamp"
250 + capabilities: {"certified":true,"control":{"mindimlevel":2000,"maxlumen":750},"streaming":{"renderer":false,"proxy":false}}
251 + config: {"archetype":"sultanbulb","function":"functional","direction":"omnidirectional","startup":{"mode":"powerfail","configured":true}}
252 + uniqueid: "00:17:xx:xx:xx:xx:xx:xx-0b"
253 + swversion: "5.127.1.26420"
254 +```
...\ No newline at end of file ...\ No newline at end of file
This diff is collapsed. Click to expand it.
1 +# Lights API
2 +
3 +The `lights` API provides a means of interacting with the lights in Hue Bridge.
4 +
5 +* [Light Object](#light-object)
6 +* [getAll()](#getAll)
7 +* [getLight()](#getlight)
8 +* [getLightById(id)](#getlightbyid): Deprecated
9 +* [getLightByName(name)](#getlightbyname)
10 +* [searchForNew()](#searchfornew)
11 +* [getNew()](#getnew)
12 +* [getLightAttributesAndState(id)](#getlightattributesandstate)
13 +* [getLightState(id)](#getlightstate)
14 +* [setLightState(id, state)](#setlightstate)
15 +* [renameLight(light)](#renamelight)
16 +* [deleteLight(id)](#deletelight)
17 +
18 +
19 +## Light Object
20 +Any function calls that will return an instance of a Light, will return a [`Light`](./light.md) instance.
21 +The `Light` object provides useful getters and setters for interacting with the Light. Consult the [documentation](./light.md)
22 +for specifics.
23 +
24 +
25 +
26 +## getAll()
27 +The `getAll()` function allows you to get all the lights that the Hue Bridge has registered with it.
28 +
29 +```js
30 +api.lights.getAll()
31 + .then(allLights => {
32 + // Display the lights from the bridge
33 + console.log(JSON.stringify(allLights, null, 2));
34 + });
35 +```
36 +
37 +This function call will resolve to an `Array` of `Light` objects.
38 +
39 +A complete code sample for this function is available [here](../examples/v3/lights/getAllLights.js).
40 +
41 +
42 +
43 +## getLight()
44 +The `getLight(id)` function allows you to retrieve a specific light.
45 +
46 +* `id`: The `id` number or a `Light` instance to retrieve from the bridge.
47 +
48 +```js
49 +api.lights.getLight(id)
50 + .then(light => {
51 + // Display the details of the light
52 + console.log(light.toStringDetailed());
53 + });
54 +```
55 +
56 +This function call will return a Promise that will resolve to a single `Light` instance.
57 +
58 +A complete code sample for this function is available [here](../examples/v3/lights/getLight.js).
59 +
60 +
61 +## getLightById()
62 +This API `getLightById(id)` has bee deprecated, use [`getLight(id)`](#getlight) instead.
63 +
64 +
65 +
66 +## getLightByName()
67 +The `getLightByName(name)` function allows you to retrieve a specific light by it's associated name value.
68 +
69 +```js
70 +api.lights.getLightByName(name)
71 + .then(light => {
72 + // Display the details of the light
73 + console.log(light.toStringDetailed());
74 + });
75 +```
76 +
77 +This function call will resolve to a single `Light` instance.
78 +
79 +A complete code sample for this function is available [here](../examples/v3/lights/getLight.js).
80 +
81 +
82 +
83 +## searchForNew()
84 +The `searchForNew()` function will initiate a search for new lights by the Hue Bridge. It will search for at least 40 seconds
85 +(but may run longer if lights are found). The search is asynchronous and performed on the bridge. To obtain the results
86 +from a previous search, use the `getNew()` API function.
87 +
88 +Calling this function whilst a search is in progress will extend the search for another 40 seconds.
89 +
90 +```js
91 +api.lights.searchForNew()
92 + .then(searchStarted => {
93 + // Display the status of the search request
94 + console.log(`Search for new lights started? ${searchStarted}`);
95 + });
96 +```
97 +
98 +The function will resolve to a `Boolean` status as to whether or no a search was activated, or extended.
99 +
100 +A complete code sample for this function is available [here](../examples/v3/lights/searchForNewLights.js).
101 +
102 +
103 +
104 +## getNew()
105 +The `getNew()` function obtains the list of Lights that were discovered from the last time a search was performed (via `searchForNew()`).
106 +Note, the lights that are provided in this API call will be cleared when a new search is initiated on the Hue Bridge.
107 +
108 +```js
109 +api.lights.getNew()
110 + .then(results => {
111 + // Display the details of the search results
112 + console.log(JSON.stringify(results, null, 2));
113 + });
114 +```
115 +
116 +The function will resolve to a JSON payload consisting of a `lastscan` property that will be set to the timestamp of the
117 +last scan that was performed.
118 +
119 +If any lights are found they will be presented under the `id` value that has been associated with the light,, e.g. 5 and the
120 +data value associate with it will be the JSON payload for the light.
121 +
122 +For example if a light of id 7 is found the returned JSON payload will be:
123 +
124 +```json
125 +{
126 + "lastscan": "2019-07-13T09:58:20",
127 + "7": {
128 + "name": "Hue Lamp 7"
129 + }
130 +}
131 +```
132 +
133 +A complete code sample for this function is available [here](../examples/v3/lights/getNewLights.js).
134 +
135 +
136 +
137 +## getLightAttributesAndState()
138 +The `getLightSttributesAndState(id)` function allows you to retrieve all the attributes and the state of a particular
139 +light from the Hue Bridge.
140 +
141 +```js
142 +api.lights.getLightAttributesAndState(id)
143 + .then(attributesAndState => {
144 + // Display the details of the light
145 + console.log(JSON.stringify(attributesAndState, null, 2));
146 + });
147 +```
148 +
149 +This will resolve to an `Object` that contains all the attributes and the current state of the light, an example of this
150 +is shown below:
151 +
152 +```json
153 +{
154 + "id": 1,
155 + "state": {
156 + "on": false,
157 + "bri": 0,
158 + "hue": 38191,
159 + "sat": 94,
160 + "effect": "none",
161 + "xy": [
162 + 0.3321,
163 + 0.3605
164 + ],
165 + "alert": "select",
166 + "colormode": "xy",
167 + "mode": "homeautomation",
168 + "reachable": true
169 + },
170 + "swupdate": {
171 + "state": "notupdatable",
172 + "lastinstall": null
173 + },
174 + "type": "Color light",
175 + "name": "Living Colour Floor",
176 + "modelid": "LLC007",
177 + "manufacturername": "Philips",
178 + "productname": "LivingColors",
179 + "capabilities": {
180 + "certified": true,
181 + "control": {
182 + "mindimlevel": 10000,
183 + "maxlumen": 120,
184 + "colorgamuttype": "A",
185 + "colorgamut": [
186 + [
187 + 0.704,
188 + 0.296
189 + ],
190 + [
191 + 0.2151,
192 + 0.7106
193 + ],
194 + [
195 + 0.138,
196 + 0.08
197 + ]
198 + ]
199 + },
200 + "streaming": {
201 + "renderer": false,
202 + "proxy": false
203 + }
204 + },
205 + "config": {
206 + "archetype": "huebloom",
207 + "function": "decorative",
208 + "direction": "upwards"
209 + },
210 + "uniqueid": "xx:xx:xx:xx:xx:xx:xx:xx-xx",
211 + "swversion": "4.6.0.8274"
212 +}
213 +```
214 +
215 +A complete code sample for this function is available [here](../examples/v3/lights/getLightAttributesAndState.js).
216 +
217 +
218 +
219 +## getLightState()
220 +You can obtain the current light state for a light using the `getLightState(id)` function.
221 +
222 +```js
223 +api.lights.getLightState(id)
224 + .then(state => {
225 + // Display the state of the light
226 + console.log(JSON.stringify(state, null, 2));
227 + });
228 +```
229 +
230 +This will resolve to an `Object` with the current state values of the light identified by the `id`. The state values
231 +returned will depend upon the type of the light and its current state values.
232 +
233 +```json
234 +{
235 + "on": false,
236 + "bri": 0,
237 + "hue": 38191,
238 + "sat": 94,
239 + "effect": "none",
240 + "xy": [
241 + 0.3321,
242 + 0.3605
243 + ],
244 + "alert": "select",
245 + "colormode": "xy",
246 + "mode": "homeautomation",
247 + "reachable": true
248 +}
249 +```
250 +
251 +A complete code sample for this function is available [here](../examples/v3/lights/getLightState.js).
252 +
253 +
254 +## setLightState()
255 +
256 +The `setLightState(id, state)` function can be used to set the state of a light specified by the `id` to the specified
257 +`state` provided.
258 +
259 +You can either provide a data object with the desired properties set for the `state` or utilize the [`LightState`](lightState.md)
260 +object to build a desired `LightState` to set.
261 +
262 +
263 +Example setting a simple light state of `on` using a simple object:
264 +```js
265 +api.lights.setLightState(id, {on: true})
266 + .then(result => {
267 + console.log(`Light state change was successful? ${result}`);
268 + })
269 +```
270 +A complete code sample for this function is available [here](../examples/v3/lights/setLightStateUsingObject.js).
271 +
272 +Example using a LightState state to set `on` and `ct` value:
273 +```js
274 +const state = new LightState().on().ct(200);
275 +
276 +api.lights.setLightState(LIGHT_ID, state)
277 + .then(result => {
278 + console.log(`Light state change was successful? ${result}`);
279 + })
280 +```
281 +
282 +The call will resolve to a `Boolean` that indicates the success status of the change.
283 +
284 +A complete code sample for this function is available [here](../examples/v3/lights/setLightStateUsingLightState.js).
285 +
286 +
287 +
288 +## renameLight()
289 +
290 +The `renameLight(id, name)` function allows you to rename the light identified by the `id` to the specified `name` value.
291 +
292 +```js
293 +api.lights.renameLight(id, 'my_new_name')
294 + .then(result => {
295 + console.log(`Successfully reanmed light? ${result}`);
296 + });
297 +````
298 +
299 +The call will resolve to a `Boolean` with the auccess status of the renaming.
300 +
301 +A complete code sample for this function is available [here](../examples/v3/lights/renameLight.js).
302 +
303 +
304 +
305 +## deleteLight()
306 +
307 +The `deletLight(id)` function will allow you to remove the light identified by the `id` value from the Hue Bridge.
308 +
309 +```js
310 +api.lights.deleteLight(lightId)
311 + .then(result => {
312 + // Display the state of the light
313 + console.log(`Successfully delete light? ${result}`);
314 + })
315 +```
316 +
317 +The call will resolve to a `Boolean` indicate a successful deletion of the light. If the light is not found, it will
318 +generate an error stating the resource is not available.
319 +
320 +A complete code sample for this function is available [here](../examples/v3/lights/deleteLight.js).
321 +
1 +# Remote API
2 +
3 +The Hue bridge can be accessed locally or remotely. The same API calls are valid for both (mostly) and this library can
4 +operate both against local and remote versions of the Hue Bridge API.
5 +
6 +For details on setting up and connecting to the `Remote Hue API` consult the [remote setup](./remoteSetup.md) docs.
7 +
8 +* [OAuthTokens Object](#oauthtokens)
9 +* [getToken()](#gettoken)
10 +* [refreshTokens()](#refreshtokens)
11 +* [createRemoteUser()](#createremoteuser)
12 +* [getRemoteAccessCredentials](#getremoteaccesscredentials)
13 +
14 +
15 +## OAuthTokens
16 +`OAuthTokens` is an Object that stores the tokens and expiry times of the related tokens. Various functions will return
17 +an instance of this Object, like `getTokens()` and `refreshTokens()`.
18 +
19 +The object has the following properties and functons:
20 +
21 +* `refreshToken`: `get` property that is the value of the refresh token
22 +* `refreshTokenExpiresAt`: `get` property that is the Unix Epoc time that the refresh token will expire
23 +* `accessToken`: `get` property that is the value of the access token
24 +* `accessTokenExpiresAt`: `get` property that is the Unix Epoc time that the access token will expire
25 +* `toString()`: `function` that will return the `String` representation of the `OAuthTokens`
26 +
27 +
28 +## getToken()
29 +The `getToken()` function allows you to exchange a `code` for a set of OAuth tokens for `access` and `refresh` activities
30 +on the `Hue Remote API`.
31 +
32 +* `code` is the authentication code that you received via the `Callback URL` from your `Hue Remote Application`.
33 +
34 +```js
35 +api.remote.getToken('magic code value')
36 + .then(tokens => {
37 + // Display the tokens
38 + console.log(JSON.stringify(tokens, null, 2));
39 + });
40 +```
41 +
42 +The function will resolve to an [`OAuthTokens` object](#oauthtokens) containing the details of the new tokens.
43 +
44 +```js
45 +{
46 + "accessToken": "AYZXfqbJXzSXetwcg9HS7V3ZmyAA",
47 + "access_expires_at": 1568298222137,
48 + "refreshToken": "NeeoF9HkPS50xAUJX8R8q2kMxUOGBGsb",
49 + "refresh_expires_at": 1577370222137
50 +}
51 +```
52 +
53 +* `access` is the OAuth Access Token that can be used to access the `Remote Hue API`
54 +* `access_expires_at` is the Unix Epoch time that the token will expire on, attempting to use the token after this time will result in failure
55 +* `refresh` is the OAuth Refresh Token that can be exchanged for new Access and Refresh tokens
56 +* `refresh_expires_at` is the Unix Epoch time that the refesh token will expire on, attempting to use the token after this time will result in failure
57 +
58 +
59 +## refreshTokens()
60 +The `refreshTokens(refreshToken)` function will exchange the `refreshToken` for a new set of OAuth tokens.
61 +
62 +```js
63 +api.remote.refreshTokens()
64 + .then(tokens => {
65 + // Display the refreshed tokens
66 + console.log(JSON.stringify(tokens, null, 2));
67 + });
68 +```
69 +
70 +The function will resolve to an [`OAuthTokens` object](#oauthtokens) containing the details of the refreshed tokens.
71 +
72 +*Note: calling this function with a valid refresh token will _expire_ the old tokens, so make sure you store the new
73 +tokens for future use. The new tokens are used immediately for all future remote API calls.*
74 +
75 +
76 +## createRemoteUser()
77 +The `createRemoteUser(remoteBridgeId, deviceType)` function will create a new remote user in the `Hue Remote API`.
78 +
79 +* `remoteBridgeId`: the integer id of the remote bridge. Unless you have multiple Hue Bridges registered in the
80 + portal, then this should be `0`. THis is an optional parameter, it will default to `0` id not specified.
81 +* `deviceType`: the name of the application/device that the user represents. This is used to visualize the user access
82 + to the end user in the portal. This is an optional parameter.
83 +
84 +```js
85 +api.remote.createRemoteUser()
86 + .then(username => {
87 + console.log(`Created a remote user: ${username}`);
88 + });
89 +```
90 +
91 +The call will resolve to the remote `username` for the user that was created.
92 +
93 +*Note: remote users are not the same as the local users that are stored inside the Hue bridge.*
94 +
95 +
96 +## getRemoteAccessCredentials()
97 +The `getRemoteAccessCredentials()` function allows you to retrieve all the remote related authentication data that
98 +the API knows about in an `Object`.
99 +
100 +```js
101 +const credentials = api.remote.getRemoteAccessCredentials();
102 +// Display the credentials
103 +console.log(JSON.stringify(credentials, null, 2));
104 +```
105 +
106 +The function will return an `Object` with the following properties:
107 +
108 +* `clientId`
109 +* `clientSecret`
110 +* `username`
111 +* `tokens`: `access` and `refresh` Objects with properties `value` and `expiresAt`
112 +
113 +The token `expiresAt` properties are the Unix epoch time values, that is millseconds since the Unix epoch and an be
114 +trivially converted into a Date object using `new Date(value)`.
115 +
116 +An example credentials object:
117 +```js
118 +{
119 + clientId: 'FSzJeGkrC6hJzPlDjC9bfxEMAQxXOvAY',
120 + clientSecret: 'YPI9z67Qh9Fjjh59',
121 + username: 'WkdWmGYI5tYVoy36ImLuLwXBwPoqxgakRnj5S0jL',
122 + tokens: {
123 + access: {
124 + value: 'AYZXfqbJXzSXetwcg9HS7V3ZmyAA',
125 + expiresAt: '1568298222137'
126 + },
127 + refresh: {
128 + value: 'NeeoF9HkPS50xAUJX8R8q2kMxUOGBGsb',
129 + expiresAt: '1577370222137'
130 + }
131 + }
132 +}
133 +```
134 +
135 +
136 +
137 +
1 +# Remote Hue API Support
2 +
3 +There is a remote access version of the Hue API that is available to users that have registered their bridges with the
4 +Philips Hue Portal.
5 +
6 +From a software perspective and this library, it does support the `Remote Hue API`, but this requires a number of things
7 +to be in place for you to be able to authenticate with the `Remote Hue API`.
8 +
9 +This library does most of the heavy lifting for you with respect to handling the various challenges that are necessary
10 +for setting up the remote OAuth tokens and users.
11 +
12 +That said it is still beneficial to understand the overall authentication flow which is detailed at:
13 +https://developers.meethue.com/develop/hue-api/remote-authentication/
14 +
15 +The steps in configuring and getting up and running with the remote API are detailed in the steps below:
16 +
17 +1. [Setup](remoteSetup.md)
18 +1. [Remote Bootstrap](remoteBootstrap.md)
19 +1. Use the `api` from the `connectXXX()` call to interact with the bridge as you would locally.
20 +
21 +
22 +## OAuth Tokens Security and Expiry
23 +Once you have successfully established a connection via the `Hue Remote API`, there will be two OAuth tokens
24 +(for access and refresh) that you need to keep hold of for future (re)connections.
25 +
26 +It is up to you as a developer/user of the library to store these securely where ever you deem appropriate, considering
27 +that these tokens provide complete remote access to your Hue Bridge via the internet!
28 +
29 +These token also have a limited window of validity, so if they are compromised at least they will expire out, eventually...
30 +
31 +Due to the tokens having an expiry, it is up to you to ensure you renew them using the `api.remote.refreshTokens()`
32 +function call, whilst the refresh token is still valid.
33 +
34 +If you let the tokens expire then you will need to perform the re-authorization against the `Hue Remote API` utilizing
35 +the `Callback URL` of your `Hue Remote API Application` and granting access, then exchanging that authorization code for
36 +the new tokens.
37 +
38 +
39 +## Examples
40 +There are working examples of establishing remote access:
41 +
42 +* [Getting remote access from scratch](../examples/v3/remote/accessFromScratch.js)
43 +* [Getting remote access using existing tokens](../examples/v3/remote/accessWithTokens.js)
...\ No newline at end of file ...\ No newline at end of file
1 +# RemoteBootstrap
2 +
3 +The `RemoteBootstrap` object provides the necessary functions to be able to configure and connect to the `Hue Remote API`.
4 +
5 +* [Creating a RemoteBootstrap](#create-a-remotebootstrap)
6 +* [getAuthCodeUrl()](#getauthcodeurl)
7 +* [connectWithCode()](#connectwithcode)
8 +* [connectWithTokens](#connectwithtokens)
9 +
10 +
11 +## Create a RemoteBootstrap
12 +To help with connecting and configuring access to the `Hue Remote API` a `RemoteBootstrap` object needs to be created
13 +that maps to your `Hue Remote API Application` that you created in the development portal.
14 +
15 +When you create a `Hue Remote API Application` under your developer account, it will be assigned a `ClientId` and
16 +`ClientSecret`. These can be obtained by opening the application that you created in the development portal following
17 +the details in the [Remote Setup](remoteSetup.md) docs.
18 +
19 +
20 +The `api.createRemote()` function requires two parameters:
21 +
22 +* `clientId`: The `ClientId` value from the `Hue Remote API application` that you create in the Hue Development Portal
23 +* `clientSecret`: The `ClientSecret` value from the `Hue Remote API application` that you created in the Hue Development Portal
24 +
25 +```js
26 +const v3 = require('node-hue-api').v3;
27 +
28 +const remoteBootstrap = v3.api.createRemote(clientId, clientSecret);
29 +```
30 +
31 +
32 +## getAuthCodeUrl
33 +The `getAuthCodeUrl(deviceId, appId, state)` function will generate the URL that you need to initiate the OAuth flow to
34 +get the OAuth tokens to access the `Hue Remote API`.
35 +
36 +* `deviceId`: `String` which is a unique identifier for the application or device using the API
37 +* `appId`: `String` which is the `AppId` of the `Hue Remote API Application` in the developer portal, you can get this
38 + from the details of the application you create
39 +* `state`: A `String` value that will be present in the response from the authentication challenge. The Hue
40 + Authorization Server roundtrips this parameter, so your application receives the same value it sent.
41 + To mitigate against cross-site request forgery (CSRF), it is strongly recommended to include an anti-forgery
42 + token in the state, and confirm it in the response. One good choice for a state token is a string of 30 or so
43 + characters constructed using a high-quality random-number generator.
44 +
45 +```js
46 +const v3 = require('node-hue-api').v3;
47 +
48 +const remoteBootstrap = v3.api.createRemote(clientId, clientSecret);
49 +console.log(remoteBootstrap.getAuthCodeUrl());
50 +```
51 +
52 +The call will return a `String` which is the URL that your end user needs to follow in the browser to perform the
53 +redirection flow that will allow them to grant your application access to their bridge over the internet.
54 +
55 +Upon a successful flow the `Callback URL` that you registered with your `Hue Remote API Application` in the developer
56 +portal. This Callback URL target will get the `state` value you passed in to the function and an authorization `code`.
57 +
58 +You should validate the `state` value before continuing, so that you can confirm that the response is from the Hue
59 +Authorization servers.
60 +
61 +*Note: The `code` that is returned in the Callback URL call is only valid for a finite time, there is nothing detailed
62 +as to the extent of the time it is valid from the Hue documentation, but it definitely longer than 25 seconds at the
63 +time of writing.*
64 +
65 +
66 +## connectWithCode
67 +The `connectWithCode(code, username, timeout, deviceType, remoteBridgeId)` function will perform the second step in the
68 +OAuth authentication process following a user granting your application access to their Hue Bridge.
69 +
70 +* `code`: The `authentication` code that you get from the Callback URL for your `Hue Remote Api Application`.
71 +* `username`: An optional `username` that has been previously created/whitelisted in the remote API.
72 +* `timeout`: An optional timeout in milliseconds for API requests.
73 +* `deviceType`: An optional `deviceType` identifier for the user that will be created _IF_ no `username` value is passed
74 + in.
75 +* `remoteBridgeId`: An optional `id` value for the remote bridge being connected to, _IF_ no value is passed will
76 + default to an id of `0` which is correct for the majority of users, as you would need to have multiple hue bridges
77 + assigned to an account before you need to specify this value.
78 +
79 +This function call will exchange the provided authorization code for new OAuth Access and Refresh tokens. These will be
80 +stored within the library as par of the call and can be retrieved later using the [`remote.getRemoteAccessCredentials()`](remote.md#getremoteaccesscredentials)
81 +call.
82 +
83 +_Note: You need to store the OAuth tokens yourself in whatever system/location you deem necessary so that you can use
84 +them again in the future, otherwise you will have to get a new authorization code using the Callback URL. **These are
85 +highly sensitive pieces of information, with them someone can fully control your bridge outside of your network!**_
86 +
87 +If you do not pass in a `username` for the connection, one will be created for you automatically due to the majority of
88 +the remote API being useless without a user. If you leave it to the library to create the user for you, you can get the
89 +`username` value from the library via the library function [`remote.getRemoteAccessCredentials()`](remote.md#getremoteaccesscredentials)
90 +
91 +```js
92 +const v3 = require('node-hue-api').v3;
93 +
94 +const remoteBootstrap = v3.api.createRemote(clientId, clientSecret);
95 +remoteBootstrap.connectWithCode(code)
96 + .then(api => {
97 + // Do something with the api like getting lights etc...
98 + })
99 +```
100 +
101 +The call will return a `Promise` that will resolve to `v3 API` object that you can use to access the bridge.
102 +
103 +
104 +## connectWithTokens
105 +The `connectWithTokens(accessToken, refreshToken, username, timeout, deviceType)` function will perform the
106 +authentication to the `Remote Hue API` using previously obtained OAuth tokens.
107 +
108 +You do not need to perform the user Callback URL process when providing existing tokens, provided that they are
109 +still valid (that is within the expiry time of their creation). Note using the refresh token you can obtain new tokens
110 +and the refresh token is valid longer than the access token, so you could wait until it expires before renewing, but
111 +there is also a time limit on the refresh token.
112 +
113 +* `accessToken`: The OAuth access token that you previously obtained (and is still valid)
114 +* `refreshToken`: The Oauth refresh token that you previously obtained (and is still valid)
115 +* `username`: An optional `username` that has been previously created/whitelisted in the remote API.
116 +* `timeout`: An optional timeout in milliseconds for API requests.
117 +* `deviceType`: An optional `deviceType` identifier for the user that will be created _IF_ no `username` value is passed
118 + in.
119 +
120 +```js
121 +const v3 = require('node-hue-api').v3;
122 +
123 +const remoteBootstrap = v3.api.createRemote(clientId, clientSecret);
124 +remoteBootstrap.connectWithTokens(code)
125 + .then(api => {
126 + // Do something with the api like getting lights etc...
127 + })
128 +```
129 +
130 +The call will return a `Promise` that will resolve to `v3 API` object that you can use to access the bridge.
131 +
132 +_Note: If you use this function to connect to the bridge, then the expiry times for the tokens will not be available
133 +within the library. If you do refresh the tokens using `api.remote.refreshTokens()` then the expiry values will be know
134 +to the library, but the tokens will be rotated adn the old ones made invalid_.
1 +# Remote API
2 +
3 +The Hue bridge can be accessed locally or remotely. The same API calls are valid for both (mostly) and this library can
4 +operate both against local and remote versions of the Hue Bridge API.
5 +
6 +
7 +## Prerequisites
8 +There are some prerequisites that must be met before you can attempt to utilize the Remote version of the Hue Bridge API.
9 +
10 +* [Developer Account on the https://developers.meethue.com portal](#registering-a-developer-account)
11 +* [Remote Hue API Application registered for your application](#creating-a-remote-hue-api-application)
12 +
13 +
14 +### Registering a Developer Account
15 +You can register for a developers account by filling in the details on the registration page, https://developers.meethue.com/register/.
16 +
17 +Once you have this account, you can sign in to the https://developer.meethue.com portal and then register your remote
18 +application with them.
19 +
20 +
21 +### Creating a Remote Hue API Application
22 +Once you have signed into the https://developers.meethue.com portal using you developers account, you can register a
23 +`Hue API Remote Application` by selecting your username in the masthead and then clicking on the `Remote Hue API appids`
24 +link.
25 +
26 +This will display your existing remote applications that you have registered as well as giving you a link to create a
27 +new application.
28 +
29 +When you click a new application, you are required to fill a number of details about your application which consist of:
30 +
31 +* `App name`: An Application name for your application, this will be what is presented to users when they authorize your
32 + application via the Remote API initial token generation
33 +* `Callback URL`: A URL that will be used in the callback when generating the necessary code for getting the Remote API
34 + OAuth tokens. This is really expected to be a URL that is valid
35 +* `Application Description`: A description of the application
36 +* `Company Details`: These appear to be optional at this time
37 +
38 +You will need to read and accept the terms and conditions for the API. It is up to you to adhere to these the library
39 +will not do anything specific to ensure you are complaint with these terms and conditions.
40 +
41 +
42 +#### Callback URL
43 +The `Callback URL` is going to be redirected to from an initial authentication grant by the user when granting access to
44 +the `Hue Remote API` by a user.
45 +
46 +This process flow ideally needs to occur in the browser and for cloud/internet hosted applications, it will not be
47 +difficult to have an endpoint exposed that will collect the information from this callback redirect and make it
48 +available to your application. It is an OAuth flow after all.
49 +
50 +If you are not hosting your application exposed to the internet, then you can still obtain the `code` that you need to
51 +exchange for tokens by registering any URL for the `Callback URL`, say `http://localhost:8080`, then the browser will
52 +still redirect to that URL along with the query parameters containing the `code` and `state`. You can then extract those
53 +values from the URL in the browser after it fails.
54 +
55 +Alternatively you can run a simple server on the `localhost` or internal network address that can be used for the
56 +`Callback URL` (currently the callback URL does support the use of `localhost`, but this may change in the future).
57 +You can then run something as simple as the following code to capture the values from the `Callback URL`:
58 +
59 +```js
60 +// Using Hapi as the server, could use express as well...
61 +const Hapi = require('@hapi/hapi');
62 +
63 +const init = async () => {
64 + const server = Hapi.server({
65 + port: 9090,
66 + host: 'localhost',
67 + });
68 +
69 + server.route({
70 + method: 'GET',
71 + path: '/',
72 + handler: (request) => {
73 + const code = request.query.code
74 + , state = request.query.state
75 + ;
76 + return {
77 + code: code,
78 + state: state
79 + }
80 + }
81 + })
82 +
83 + await server.start();
84 + console.log('Server running on %s', server.info.uri);
85 +}
86 +
87 +process.on('unhandledRejection', (err) => {
88 + console.log(err);
89 + process.exit(1);
90 +});
91 +
92 +init();
93 +```
94 +
95 +
96 +## Connecting with the Remote API
97 +
98 +Once you have set up the `Remote API Application` with the https://developers.meethue.com portal, you can then use the
99 +application data along with the library to generate your OAuth tokens needed for remote access.
100 +
101 +Navigate to your `Remote Hue API Application` and collect the `ClientId` and `ClientSecret` along with the `AppId` for
102 +the remote application, these are needed so that we can talk with the Hue Remote API endpoints.
103 +
104 +There are two possible paths that you have for accessing the Hue Remote API;
105 +
106 +* [New Connection to the Remote Hue API Application](#new-remote-application-connection)
107 +* [Reusing an existing Access Token to connect to the Remote Hue API](#)
108 +
109 +
110 +### New Remote Application Connection
111 +
112 +In this scenario you have never generated (or lost your previous) OAuth Access Token to the Remote Hue API. The flow that
113 +the Hue Remote API requires in this case is:
114 +
115 +1. An access URL is generated that the user can issue an HTTP GET on (this includes a `state`) code which you can use
116 + to detect forgeries from your application code.
117 +1. User navigates to the provided URL, which will redirect them to sign in to the https://account.meethue.com website
118 +1. After the user is signed in, they will prompted with a `Grant permission` page that will show the name of your
119 + application (the `AppId`), that they must accept to grant you access to their account and bridges.
120 +1. Once the user accepts the grant request, they will be redirected to the `Callback URL` of the Hue Remote Application
121 + that you set up above. There will be two query parameters in the callback URL that the user is redirected to,
122 + `code` and `state`.
123 +1. The `code` and `state` parameters that are received in the callback need to be collected. The `state` is the same
124 + `state` value that was passed in via the initial access URL, you can validate this to ensure that the response is
125 + associated with the one you sent. The `code` is the value you need to exchange with the Remote Hue API to obtain
126 + your OAuth Access Token.
127 +1. Call the `connectWithCode(code, username)` function to exchange your code for OAuth Access and Refresh Tokens
128 +1. Interact with the remote bridge (after you have stored the tokens for future use) using this library API.
129 +
130 +
131 +### Reusing Existing OAuth Tokens
132 +
133 +In this scenario, you have already gone through the [New Remote Application Connection](#new-remote-application-connection)
134 +process and stored the `Access Token` and `Refresh Token` so that you can reuse them.
135 +
136 +1. Instantiate a remote api via the library
137 +1. Call `connectWithTokens()` function to attach to the `Hue Remote API` using the provided tokens
138 +1. Interact with the remote bridge using this library API
139 +
140 +*Note: You are responsible for passing a valid unexpired access and/or refresh token. The tokens will expire after a
141 +period of time, the times of which are availble via the API when they are first obtained.*
142 +
143 +
144 +## Remote Users / Whitelist
145 +The remote API is fairly useless unless you have a remote user created. The library will create a new user for you in the
146 +`Hue Remote API` whitelist if you do not pass in an existing username. *Note, this is different to the approach that is taken
147 +with the local API connections of this library.*
148 +
149 +When you call either `connectWithCode()` or `connectWithTokens()` and do not provide a `username` parameter a new remote
150 +user will be created as part of the connection to the remote API. The reason for doing this is to make the remote API
151 +more usable as unlike the local API, where you now need to press the link button on the bridge, this can be automated
152 +via the `Hue Remote API`.
153 +
154 +If you are not passing an existing `username` when connecting, you can collect the username that was created at
155 +connection time using the [`api.remote.getRemoteAccessCredentials()`]() function.
156 +
157 +
158 +
1 +# ResourceLink
2 +
3 +A `ResourceLink` is a grouping construct for various Hue Bridge resources that are linked to provide some level of
4 +interconnected functionality. This is used primarily for the Hue Formulas, but can be leveraged by API developers as an
5 +advanced mechanism for building advanced functionality.
6 +
7 +
8 +* [Create a ResourceLink](#creating-a-resourcelink)
9 +* [ResourceLink Properties and Functions](#resourcelink-properties-and-functions)
10 +
11 +
12 +## Creating a ResourceLink
13 +
14 +You can create a `ResourceLink` by using the `v3.model.createResourceLink()` function.
15 +
16 +```js
17 +const Scene = require('node-hue-api').v3.model;
18 +const myResourceLink = model.createResourceLink();
19 +```
20 +
21 +
22 +## ResourceLink Properties and Functions
23 +
24 +* [id](#id)
25 +* [name](#name)
26 +* [description](#description)
27 +* [type](#type)
28 +* [classid](#classid)
29 +* [owner](#owner)
30 +* [recycle](#recycle)
31 +* [links](#links)
32 + * [resetLinks()](#resetlinks)
33 + * [addLink()](#addlink)
34 + * [removeLink()](#removelinks)
35 +* [toString](#tostring)
36 +* [toStringDetailed](#tostringdetailed)
37 +
38 +
39 +
40 +
41 +### id
42 +Get the `id` for the ResourceLink.
43 +* `get`
44 +
45 +
46 +### name
47 +Get/Set a name for the ResourceLink.
48 +* `get`
49 +* `set`
50 +
51 +
52 +### description
53 +Get/Set a description for the ResourceLink.
54 +* `get`
55 +* `set`
56 +
57 +
58 +### type
59 +Get the type of the ResourceLink, which is always `Link` at the current time.
60 +* `get`
61 +
62 +
63 +### classid
64 +Get/Set a classid for the ResourceLink. This is specific to the application and can be used to identify the purpose of
65 +the ResourceLink.
66 +
67 +The Hue API documentation gives the following example use case:
68 +
69 + The resourcelink class can be used to identify resourcelink with the same purpose, like classid 1 for wake-up, 2 for going to sleep, etc. (best practice use range 1 – 10000)
70 +
71 +* `get`
72 +* `set`
73 +
74 +
75 +### owner
76 +Gets the owner of the ResourceLink, which is only populated on ResourceLinks obtained from the Hue Bridge.
77 +* `get`
78 +
79 +
80 +### recycle
81 +Get/Set the `recyle` attribute of the ResourceLink. This is used to flag scenes that can be automatically deleted by
82 +the bridge.
83 +
84 +If the `recycle` state is set to `false` the Hue bridge will keep the ResourceLink until an application removes it.
85 +* `get`
86 +* `set`
87 +
88 +
89 +### links
90 +There is a property on the ResourceLink `links` that will return a copy of the existing links object defined in the
91 +ResourceLink.
92 +
93 +* `get`
94 +
95 +The object returned will have a key value of the name of the type of link (e.g. `groups`) and an Array of the ids for the
96 +linked items of that type. Any types of links that have no items, will not be present in the links object.
97 +
98 +For example if we had links for lights with ids `1`, `2` and `3` and group `0` the `links` object would look like:
99 +
100 +```json
101 +{
102 + "lights": [1, 2, 3],
103 + "groups": [0]
104 +}
105 +```
106 +
107 +
108 +#### resetLinks()
109 +A function `resetLinks()` will clear out any existing links on the ResourceLink.
110 +
111 +
112 +#### addLink()
113 +The function `addLink(type, id)` allows for the adding of a link to the ResourceLink.
114 +
115 +* `type`: One of the supported types:
116 + * `lights`
117 + * `sensors`
118 + * `groups`
119 + * `scenes`
120 + * `rules`
121 + * `schedules`
122 + * `resourcelinks`
123 +* `id`: The id of the type of object that you are adding as a link, e.g. a group id if the the `type` was a group
124 +
125 +
126 +#### removeLink()
127 +The function `removeLink(type, id)` allows for the removal of a specific link from the ResourceLink.
128 +
129 +* `type`: One of the supported types:
130 + * `lights`
131 + * `sensors`
132 + * `groups`
133 + * `scenes`
134 + * `rules`
135 + * `schedules`
136 + * `resourcelinks`
137 +* `id`: The id of the type of object that you are removing as a link, e.g. a group id if the the `type` was a group
138 +
139 +
140 +
141 +### toString()
142 +The `toString()` function will obtain a simple `String` representation of the Scene.
143 +
144 +
145 +### toStringDetailed()
146 +The `toStringDetailed()` function will obtain a more detailed representation of the Scene object.
...\ No newline at end of file ...\ No newline at end of file
1 +# ResourceLinks API
2 +
3 +The `resourceLinks` API provides a means of interacting with the `ResourceLinks` in Hue Bridge.
4 +
5 +A `ResourceLink` is a collection/grouping mechanism for linking various bridge resources that are interconnected. The
6 +Hue Formulas that you add to your bridge are examples of these.
7 +
8 +See [`ResourceLink`s](./resourceLink.md) for more details on the `ResourceLink` objects
9 +
10 +
11 +* [getAll()](#getall)
12 +* [getResourceLink(id)](#getresourcelink)
13 +* [getResourceLinkByName(name)](#getresourcelinkbyname)
14 +* [createResourceLink()](#createresourcelink)
15 +* [updateResouceLink()](#updateresourcelink)
16 +* [deleteResourceLink()](#deleteresourcelink)
17 +
18 +
19 +## getAll()
20 +The `getAll()` function allows you to get all the `ResourceLinks` that the Hue Bridge has registered with it.
21 +
22 +```js
23 +api.resourceLinks.getAll()
24 + .then(allResourceLinks => {
25 + // Display the ResourceLinks from the bridge
26 + allResourceLinks.forEach(resourceLink => {
27 + console.log(resourceLink.toStringDetailed());
28 + });
29 + });
30 +```
31 +
32 +This function call will resolve to an `Array` of `ResourceLink` objects.
33 +
34 +A complete code sample for this function is available [here](../examples/v3/resourceLinks/getAllResourceLinks.js).
35 +
36 +
37 +
38 +## getResourceLink()
39 +The `getResourceLink(id)` function allows a specific `ResourceLink` to be retrieved from the Hue Bridge.
40 +
41 +* `id`: The `String` id of the `ResourceLink` to retrieve.
42 +
43 +
44 +```js
45 +api.resourceLinks.getResourceLink(62738)
46 + .then(resourceLink => {
47 + console.log(resourceLink.toStringDetailed());
48 + })
49 +;
50 +```
51 +
52 +This function call will resolve to a `ResourceLink` object for the specified `id`.
53 +
54 +If the `ResourceLink` cannot be found an `ApiError` will be returned with a `getHueErrorType()` value of `3`.
55 +
56 +A complete code sample for this function is available [here](../examples/v3/resourceLinks/getResourceLink.js).
57 +
58 +
59 +## getResourceLinkByName()
60 +The `getResourceLinkByName(name)` function will retrieve all `ResourceLink` instances that match the provided name from the Hue Bridge.
61 +
62 +* `name`: The `String` name of the `ResourceLink` to retrieve.
63 +
64 +
65 +```js
66 +api.resourceLinks.getResourceLink(62738)
67 + .then(resourceLink => {
68 + console.log(resourceLink.toStringDetailed());
69 + })
70 +;
71 +```
72 +
73 +This function call will resolve to a `ResourceLink` object for the specified `id`.
74 +
75 +If the `ResourceLink` cannot be found an `ApiError` will be returned with a `getHueErrorType()` value of `3`.
76 +
77 +A complete code sample for this function is available [here](../examples/v3/resourceLinks/getResourceLink.js).
78 +
79 +
80 +
81 +
82 +## createResourceLink()
83 +The `createResourceLink(ResourceLink)` function allows for the creation of new `ResourceLink`s in the Hue Bridge.
84 +
85 +* `resourceLink`: A `ResourceLink` object that has been configured with the desired settings that you want to store.
86 +
87 +```js
88 +const resourceLink = v3.model.createResourceLink();
89 +resourceLink.name = 'My Resource Link';
90 +resourceLink.description = 'A test resource link for node-hue-api';
91 +resourceLink.recycle = true;
92 +resourceLink.classid = 100;
93 +resourceLink.addLink('groups', 0);
94 +
95 +api.resourceLinks.createResourceLink(resourceLink)
96 + .then(resourceLink => {
97 + console.log(`Successfully created ResourceLink\n${resourceLink.toStringDetailed()}`);
98 + })
99 +;
100 +```
101 +
102 +The function will resolve with a corresponding `ResourceLink` object that was created.
103 +
104 +A complete code sample for this function is available [here](../examples/v3/resourceLinks/createAndDeleteResourceLink.js).
105 +
106 +
107 +
108 +## updateResourceLink()
109 +The `updateResourceLink(resourceLink)` function allows you to update an existing `ResourceLink` in the Hue Bridge.
110 +
111 +* `resourceLink`: A `ResourceLink` object that was obtained from the API and then updated with the appropriate data changes to apply.
112 +
113 +```js
114 +// A resourceLink needs to be obtained from the bridge first, assume one has called "resourceLink"
115 +resourceLink.name = 'Updated ResourceLink Name';
116 +
117 +api.resourceLink.updateResourceLink(resourceLink);
118 + .then(updated => {
119 + console.log(`Updated ResourceLink properties: ${JSON.stringify(updated)}`);
120 + })
121 +;
122 +```
123 +
124 +The function will resolve to an object that contains the attribute names of the `ResourceLink` that were updated set
125 +to the success status of the change to the attribute.
126 +
127 +_Note currently no checks are performed against the existing attributes, so all updatable attributes are sent to the bridge
128 +when invoking this function._
129 +
130 +For example, the result from the above example would resolve to:
131 +
132 +```js
133 +{
134 + "name": true,
135 + "description": true,
136 + "classid": true,
137 + "links": true
138 +}
139 +```
140 +
141 +A complete code sample for this function is available [here](../examples/v3/resourceLinks/updateResourceLink.js).
142 +
143 +
144 +
145 +
146 +## deleteResourceLink()
147 +The `deleteResourceLink(id)` function will delete the specified `ResourceLink` identified by the `id` from the Hue Bridge.
148 +
149 +* `id`: The `id` of the `ResourceLink` to delete from the Hue Bridge, or a `ResourceLink` object that was obtained from
150 + the Hue Bridge
151 +
152 +```js
153 +api.resourceLinks.deleteResourceLink('abc170f')
154 + .then(result => {
155 + console.log(`Deleted ResourceLink? ${result}`);
156 + })
157 +;
158 +```
159 +
160 +The call will resolve to a `Boolean` indicating the success status of the deletion.
161 +
162 +A complete code sample for this function is available [here](../examples/v3/resourceLinks/createAndDeleteResourceLink.js).
163 +
1 +# Rule Objects
2 +
3 +The Hue Bridge supports Rules to define complex automation activities. The `Rule` object can be built up to support a
4 +number of `RuleConditions` which when all evaluating to `true` will trigger one or more `RuleActions` to modify states
5 +of Lights, Groups, CLIP Sensors or Schedules.
6 +
7 +* [Creating a New Rule](#creating-a-rule)
8 +* [Rule Properties](#rule-properties)
9 + * [id](#id)
10 + * [name](#name)
11 + * [owner](#owner)
12 + * [lasttriggered](#lasttriggered)
13 + * [timestriggered](#timestriggered)
14 + * [status](#status)
15 + * [recycle](#recycle)
16 + * [conditions](#conditions)
17 + * [actions](#actions)
18 + * [toString()](#tostring)
19 + * [toStringDetailed()](#tostringdetailed)
20 +* [addCondition()](#addconditioncondition)
21 +* [removeConditionAt(idx)](#removeconditionatidx)
22 +* [clearConditions()](#clearconditions)
23 +* [addAction()](#addactionaction)
24 +* [removeActionAt(idx)](#removeactionatidx)
25 +* [clearActions()](#clearactions)
26 +
27 +
28 +## Creating a Rule
29 +
30 +You can create a `Rule` by using the `new` operator.
31 +
32 +```js
33 +const Rule = require('node-hue-api').v3.rules.Rule;
34 +const myRule = new Rule();
35 +```
36 +
37 +All Rules MUST have at least one `RuleCondition` and `RuleAction` associated with them for the Bridge to consider them
38 +valid. You can add these to a `Rule` using the [`addAction(action)`](#addactionaction) and [`addCondition(condition)`](#addactionaction)
39 +functions on the `Rule`.
40 +
41 +Consult the [`RuleAction`](./ruleAction.md) and [`RuleCondition`](./ruleCondition.md) documentation for creating the
42 +various types of Actions and Conditions for a Rule.
43 +
44 +
45 +## Rule Properties
46 +
47 +* [id](#id)
48 +* [name](#name)
49 +* [owner](#owner)
50 +* [lasttriggered](#lasttriggered)
51 +* [timestriggered](#timestriggered)
52 +* [status](#status)
53 +* [recycle](#recycle)
54 +* [conditions](#conditions)
55 +* [actions](#actions)
56 +* [toString()](#tostring)
57 +* [toStringDetailed()](#tostringdetailed)
58 +
59 +### id
60 +Get the `id` for the Scene.
61 +* `get`
62 +
63 +### name
64 +Get/Set a name for the Scene.
65 +* `get`
66 +* `set`
67 +
68 +### owner
69 +Gets the owner of the Scene.
70 +* `get`
71 +
72 +### lasttriggered
73 +Gets the last triggered time for the Rule.
74 +* `get`
75 +
76 +### timestriggered
77 +Gets the number of times that the Rule has been triggered
78 +* `get`
79 +
80 +### status
81 +Gets the status of the Rule, which can be `enabled`, `resourcedeleted` and possibly other states, but these are not
82 +documented via the Hue API.
83 +* `get`
84 +
85 +### recycle
86 +Get/Set the `recyle` attribute of the Rule. This is used to flag scenes that can be automatically deleted by the bridge.
87 +If the `recycle` state is set to `false` the Hue bridge will keep the scene until an application removes it.
88 +* `get`
89 +* `set`
90 +
91 +### conditions
92 +Gets the `RuleCondition`s that are set on the Rule. These are the conditions that all must evaluate to `true` to
93 +trigger the rule's `RuleAction`s.
94 +* `get`
95 +
96 +### actions
97 +Gets the `RuleAction`s that are set on the Rule. These are the actions that will be triggered if the all the `RuleCondtion`s
98 +evaluate to `true`.
99 +* `get`
100 +
101 +
102 +### toString()
103 +The `toString()` function will obtain a simple `String` representation of the Scene.
104 +
105 +
106 +### toStringDetailed()
107 +The `toStringDetailed()` function will obtain a more detailed representation of the Scene object.
108 +
109 +
110 +## addCondition(condition)
111 +The `addCondition(condition)` function will add a new `RuleCondition` to the existing conditions on the `Rule`.
112 +
113 +* `condition`: The new `RuleCondition` to be added.
114 +
115 +Consult the [RuleCondition](./ruleCondition.md) documentation on creating a `RuleCondition` instance.
116 +
117 +
118 +## removeConditionAt(idx)
119 +The `removeConditionAt(idx)` function will remove the `RuleCondition` that is at the specified index `idx` from the Array
120 +of `RuleConditions` on the `Rule`.
121 +
122 +* `idx`: The index of the `RuleCondition` in the Rule to remove.
123 +
124 +
125 +## clearConditions()
126 +The `clearConditions()` function will reset all the conditions on the Rule to an empty `Array`. You will need to add at
127 +least one `RuleCondition` after do this for the Rule to be valid.
128 +
129 +
130 +## addAction(action)
131 +The `AddAction(action)` function will add a new `RuleAction` to the existing actions on the `Rule`.
132 +
133 +* `action`: The new `RuleAction` to be added.
134 +
135 +Consult the [RuleAction](./ruleAction.md) documentation on creating a `RuleAction` instance.
136 +
137 +## removeActionAt(idx)
138 +The `removeActionAt(idx)` function will remove the `RuleAction` at the specified `idx` index value from the
139 +`RuleActions` on the `Rule`.
140 +
141 +* `idx`: The index of the `RuleAction` in the Rule to remove.
142 +
143 +
144 +## clearActions()
145 +The `clearActions()` function will reset all the actions on the Rule to an empty `Array`. You will need to add at least
146 +one `RuleAction` after this for the Rule to be valid.
...\ No newline at end of file ...\ No newline at end of file
1 +# RuleAction
2 +
3 +A `RuleAction` is an object that defines an action that can be performed when a `Rule` is triggered in the Hue Bridge.
4 +
5 +There are a number of different types of `RuleAction`s that can be built and to aid in this, the API provides a
6 +fluent interface for building up the various `RuleActions`s for `Rule`s.
7 +
8 +* [Instantiating a RuleAction](#instantiating-an-action)
9 +* [RuleAction](#ruleaction)
10 + * [LightStateAction](#lightstateaction)
11 + * [GroupStateAction](#groupstateaction)
12 + * [SensorStateAction](#sensorstateaction)
13 + * [SceneAction](#sceneaction)
14 +
15 +
16 +
17 +## Instantiating a RuleAction
18 +A `RuleAction` can be built using the `v3.model.ruleActions` Object, currently this allows for the creation of actions
19 +via the functions:
20 +
21 +* `light`: Creates a [`LightStateAction`](#lightstateaction) that will set a `LightState` on a specific `Light`
22 +* `group`: Creates a [`GroupStateAction`](#groupstateaction) that will set a state `GroupLightState` on a `Group`
23 +* `sensor`: Creates a [`SensorStateAction`](#sensorstateaction) that will set a state on a `CLIPSensor` Object
24 +
25 +
26 +## RuleAction
27 +The base `RuleAction` class is a common base to all `RuleAction` types. It has the following properties and functions:
28 +
29 +* `address`: `get` the address target for the `RuleAction`
30 +* `body`: `get` the body payload for the `RuleAction`
31 +* `id`: `get` the id for the target of the `RuleAction`, e.g. the Light id, Group id, Sensor id
32 +* `method`: `get` the method of the `RuleAction`, in most cases this is `PUT` as the majority of actions are updates
33 +* `withMethod(method)`: sets the method of the `RuleAction`
34 +* `toString()`: Obtains a String representation of the `RuleAction`
35 +* `payload()`: Obtains the payload that is set into the Hue Bridge for the `RuleAction` when the `Rule` is updated/created
36 +
37 +---
38 +
39 +### LightStateAction
40 +A `LightStateAction` is a `RuleAction` that will help in constructing the `RuleAction` for setting a `LightState` on a `Light`
41 +when a rule is triggered.
42 +
43 +It contains all the properties and functions for [`RuleAction`](#ruleaction) above.
44 +
45 +
46 +#### Instantiation
47 +To get an instance of a `LightStateAction` use the function `v3.rules.actions.light(id)`
48 +
49 +* `id`: The id for the light or a `Light` instance obtained from the bridge
50 +
51 +The function will return an instance of a `LightStateAction`.
52 +
53 +
54 +#### withState(state)
55 +The `withState(state)` function allows you to specify the state that will be applied to the `Light`.
56 +
57 +* `state`: The [`LightState`](lightState.md) to apply to the `Light`, or a JSON payload of attributes that will be transformed in a `LightState`, e.g. `{on: true}`.
58 +
59 +The function will return the instance of the `LightStateAction` so you can chain calls.
60 +
61 +---
62 +
63 +
64 +### GroupStateAction
65 +A `GroupStateAction` is a `RuleAction` that will help in constructing the `RuleAction` for setting a `GroupLightState`
66 +on a `Group` when a rule is triggered.
67 +
68 +It contains all the properties and functions for [`RuleAction`](#ruleaction) above.
69 +
70 +
71 +#### Instantiation
72 +To get an instance of a `GroupStateAction` use the function `v3.rules.actions.group(id)`
73 +
74 +* `id`: The id for the group or a `Group` instance obtained from the bridge
75 +
76 +The function will return an instance of a `GroupStateAction`.
77 +
78 +
79 +#### withState(state)
80 +The `withState(state)` function allows you to specify the state that will be applied to the `Group`.
81 +
82 +* `state`: The [`GroupLightState`](lightState.md) to apply to the `Group`, or a JSON payload of attributes that will be transformed in a `GroupLightState`, e.g. `{on: true}`.
83 +
84 +The function will return the instance of the `GroupStateAction` so you can chain calls.
85 +
86 +---
87 +
88 +### SensorStateAction
89 +A `SensorStateAction` is a `RuleAction` that will help in constructing the `RuleAction` for setting a `Sensor`s state
90 +attributes when a rule is triggered.
91 +
92 +It contains all the properties and functions for [`RuleAction`](#ruleaction) above.
93 +
94 +
95 +#### Instantiation
96 +To get an instance of a `SensorStateAction` use the function `v3.rules.actions.sensor(id)`
97 +
98 +* `id`: The id for the sensor or a `Sensor` instance obtained from the bridge
99 +
100 +The function will return an instance of a `SensorStateAction`.
101 +
102 +
103 +#### withState(state)
104 +The `withState(state)` function allows you to specify the state that will be applied to the `Sensor`.
105 +
106 +* `state`: A JSON payload of attributes that will be modified on the `Sensor`, e.g: `{flag: true}`
107 +
108 +The function will return the instance of the `SensorStateAction` so you can chain calls.
109 +
110 +---
111 +
112 +### SceneAction
113 +A `SceneAction` is a `RuleAction` that will help to constructo a `RuleAction` for saving a `Scene`'s state when triggered
114 +
115 +It contains all the properties and functions for [`RuleAction`](#ruleaction) above.
116 +
117 +#### Instantiation
118 +To get an instance of a `SensotStateAction` use the function `v3.rules.actions.scene(id)`
119 +
120 +* `id`: The id for the sensor or a `Scene` instance obtained from the bridge
121 +
122 +The function will return an instance of a `SceneAction`.
123 +
124 +
125 +#### withState(state)
126 +The `withState(state)` function allows you to specify the state that will be applied to the `Scene`.
127 +
128 +* `state`: A JSON payload of attributes that will be modified on the `Sensor`, e.g: `{storelightstate: true}`
129 +
130 +The function will return the instance of the `SceneAction` so you can chain calls.
131 +
132 +
133 +---
...\ No newline at end of file ...\ No newline at end of file
1 +# RuleCondition
2 +
3 +A `RuleCondition` is an object that defines a condition that can be used to trigger a `Rule` in the Hue Bridge.
4 +
5 +There are a number of different types of RuleConditions that can be built and to aid in this, the API provides a
6 +fluent interface for building up the various `RuleCondition`s for `Rule`s.
7 +
8 +
9 +* [Condition Builders](#condition-builders)
10 +* [SensorCondition Builder](#sensorcondition-builder)
11 + * [when(attribute)](#whenattribute)
12 + * [Sensor Attribute Operator](#sensor-attribute-operator)
13 + * [getRuleCondition()](#getrulecondition)
14 + * [Examples](#sensorcondition-examples)
15 +* [GroupCondition Builder](#groupcondition-builder)
16 + * [when()](#when)
17 + * [Group Attribute Selector](#group-attribute-selector)
18 + * [Group Attribute Operator](#group-attribute-operator)
19 + * [getRuleCondition()](#getrulecondition-1)
20 + * [Examples](#groupcondition-examples)
21 +
22 +
23 +## Condition Builders
24 +
25 +A `RuleCondition` can be built using the `v3.model.ruleCconditions` Object, currently this allows for the creation of
26 +conditions for `Sensors` and `Groups`.
27 +
28 +
29 +## SensorCondition Builder
30 +
31 +A `SensorCondition` builder can be created using the `v3.model.ruleConditions.sensor(sensor)` function.
32 +
33 +* `sensor`: The `Sensor` obtained from bridge via the API that you wish to use in a condition.
34 +
35 +You have to provide a `Sensor` object from the Hue Bridge (you can use the [Sensors API](./sensors.md) to get an
36 +instance of the one you desire).
37 +
38 +```js
39 +const v3 = require('node-hue-api').v3
40 + , conditions = v3.model.ruleConditions;
41 +
42 +const mySensor = await v3.sensors.get(sesnorId);
43 +const mySensorCondition = conditions.sensor(mySensor);
44 +// Then build the condition using the functions/properties on the SensorConditions
45 +```
46 +
47 +### when(attribute)
48 +The `whne(attribute)` function specifies the target attribute of the sensor to set the condition on. The attributes vary
49 +on the Sensors based on what type of sensor that it is.
50 +
51 +* `attribute`: The String name of the attribute for the `Sensor` that you are applying the condition to
52 +
53 +For example a `CLIPGenericFlag` has an attribute of `flag` that is a `boolean` flag that can be monitored.
54 +
55 +This function will return an `Object` that allows you to select the appropriate `RuleOperator` by invoking an appropriate
56 +function, see below for more details.
57 +
58 +#### Sensor Attribute Operator
59 +
60 +* `equals(val)`: The specified attribute equals `val`, compatible with `boolean` and `int` attributes
61 +* `greaterThan(val)`: The specified attribute is greater than `val`, compatible with `int` attributes
62 +* `lessThan(val)`: The specified attribute is less than `val`, compatible with `int` attributes
63 +* `changed()`: The specified attribute has changed
64 +* `changedDelayed(val)`: The specified attribute changed within a `val` interval period (a delayed change)
65 +* `stable(val)`: The specified attribute has not changed in a specified `val` interval
66 +* `notStable(val)`: The specified attribute has changed in a specified `val` interval
67 +* `in(val)`: Current time is within the specified interval, triggered on starttime
68 +* `notIn(val)`: Current time is not with the specified interval, triggered on endtime
69 +
70 +Any of these functions when called will return the `SensorCondition` object that you started with.
71 +
72 +### getRuleCondition()
73 +The `getRuleCondition()` function will generate the `RuleCondition` instance that has been built from the various
74 +calls that you have made via the fluent API for the builder.
75 +
76 +This will return a `RuleCondition` if the provided configuration is valid. Otherwise it will throw and `ApiError`.
77 +
78 +Note: Not every aspect of the condition can be checked at this point, and as such the final validation will be performed
79 +via the Hue Bridge when the `RuleCondition` is saved/updated on a `Rule`.
80 +
81 +
82 +### SensorCondition Examples
83 +
84 +The following are code examples of setting up various SensorConditions.
85 +
86 +Create a `RuleCondition` that will trigger on a `flag` attribute change on a CLIPGenericFlag Sensor (i.e. trigger on every change):
87 +```js
88 +const v3 = require('node-hue-api').v3
89 + , conditions = v3.model.ruleConditions
90 +;
91 +
92 +// Create a SensorCondition that will trigger on a flag attribute change for the CLIPGenericFlag Sensor:
93 +const sensorCondition = conditions.sensor(aFlagSensor).when('flag').changed();
94 +const ruleCondition = sensorCondition.getRuleCondition();
95 +```
96 +
97 +Create a RuleCondition that will trigger when the `flag` attribute changes to `true` for a CLIPGenericFlag Sensor:
98 +```js
99 +const v3 = require('node-hue-api').v3
100 + , conditions = v3.model.ruleConditions
101 +;
102 +
103 +// Create a SensorCondition that will trigger on the flag attribute being true CLIPGenericFlag Sensor:
104 +const sensorCondition = conditions.sensor(aFlagSensor).when('flag').equals(true);
105 +const ruleCondition = sensorCondition.getRuleCondition();
106 +```
107 +
108 +
109 +## GroupCondition Builder
110 +
111 +A `GroupCondition` builder can be created using the `v3.model.ruleConditions.group(id)` function.
112 +
113 +* `id`: The id for the group (or the Group instance) that you wish to build the condition on
114 +
115 +You can pass in either the id value for the group or a `Group` instance from the API to start building the condition.
116 +
117 +### when()
118 +The `when()` function obtains the Attribute selector for the group which allows you to select the desired Group attribute
119 +that the condition will be built from.
120 +
121 +#### Group Attribute Selector
122 +There are only two attributes for a group that can be used to build a condition on which are exposed via the following
123 +functions:
124 +
125 +* `allOn()`: Boolean attribute that is `true` when ALL the lights in a group are on
126 +* `anyOn()`: Boolean attribute that is `true` when ANY of the lights in a group are on
127 +
128 +Either of these functons will return an Operator Selector object that will allow you to set the operator (and possible value)
129 +on the condition that you are building.
130 +
131 +#### Group Attribute Operator
132 +
133 +* `equals(val)`: The attribute equals the specified `val`
134 +* `changed()`: The attribute is changed
135 +* `changedDelayed(val)`: The attribute is a delayed changed within a period `val`
136 +
137 +Any of these functions will return the `GroupCondition` that you started with.
138 +
139 +
140 +### getRuleCondition()
141 +The `getRuleCondition()` function will generate the `RuleCondition` instance that has been built from the various
142 +calls that you have made via the fluent API for the builder.
143 +
144 +This will return a `RuleCondition` if the provided configuration is valid. Otherwise it will throw and `ApiError`.
145 +
146 +Note: Not every aspect of the condition can be checked at this point, and as such the final validation will be performed
147 +via the Hue Bridge when the `RuleCondition` is saved/updated on a `Rule`.
148 +
149 +### GroupCondition Examples
150 +
151 +The following are code examples of setting up various GroupConditions.
152 +
153 +Create a `GroupCondition` that will trigger when any light is on in a group:
154 +```js
155 +const v3 = require('node-hue-api').v3
156 + , conditions = v3.model.ruleConditions
157 +;
158 +
159 +// Create a SensorCondition that will trigger on a flag attribute change for the CLIPGenericFlag Sensor:
160 +const groupCondition = conditions.group(groupId).when().anyOn().equals(true);
161 +const ruleCondition = groupCondition.getRuleCondition();
162 +```
1 +# Rules API
2 +
3 +The `rules` API provides a manes of interacting with Rules in the Hue Bridge.
4 +
5 +Rules are complex event triggers that consist of a one or more conditions that must be satisfied, which when they are
6 +will trigger one or more actions for devices connected to the bridge.
7 +
8 +The Actions can consist of Group, Light or Sensor state changes.
9 +
10 +It is possible to build up some very complex logic/triggering with the use of rules, and with the use of CLIP Sensors
11 +you can potentially build up some interesting automation scenarios.
12 +
13 +
14 +The Rules API interacts with specific [`Rule`](./rule.md) objects from the Bridge.
15 +
16 +
17 +* [getAll()](#getall)
18 +* [getRule(id)](#getrule)
19 +* [getRuleByName(name)](#getrulebyname)
20 +* [createRule(rule)](#createrule)
21 +* [deleteRule(id)](#deleterule)
22 +* [updateRule(rule)](#updaterule)
23 +
24 +
25 +## getAll()
26 +The `getAll()` function will obtain all the Rules that are defiend in the Hue Bridge.
27 +
28 +```js
29 +api.rules.getAll()
30 + .then(allRules => {
31 + // Display the Rules
32 + allRules.forEach(rule => {
33 + console.log(rule.toStringDetailed())
34 + });
35 + });
36 +```
37 +
38 +This function call will resolve to an `Array` of `Rule` objects.
39 +
40 +A complete code sample for this function is available [here](../examples/v3/rules/getAllRules.js).
41 +
42 +
43 +## getRule()
44 +The `getRule(id)` function will obtain the specified Rule with the given `id`.
45 +
46 +* `id`: The id for the rule, or a `Rule` instance to get from the Hue Bridge.
47 +
48 +```js
49 +api.rules.getRule(1)
50 + .then(rule => {
51 + // Display the Rule
52 + console.log(rule.toStringDetailed());
53 + });
54 +```
55 +
56 +This function will return a `Rule` object for the specified `id`.
57 +
58 +A complete code sample for this function is available [here](../examples/v3/rules/getRule.js).
59 +
60 +
61 +## getRuleByName()
62 +The `getRuleByName(name)` function will obtain all the `Rule`s from the bridge that have the specified `name`.
63 +
64 +* `name`: The name of the `Rule`s to get from the Hue Bridge.
65 +
66 +```js
67 +api.rules.getRuleByName('Opened door')
68 + .then(allRules => {
69 + // Display the Rules
70 + allRules.forEach(rule => {
71 + console.log(rule.toStringDetailed());
72 + });
73 + });
74 +```
75 +
76 +This function will return an `Array` of `Rule` objects for all of the `Rule`s that matched the specided `name`.
77 +
78 +A complete code sample for this function is available [here](../examples/v3/rules/getRuleByName.js).
79 +
80 +
81 +
82 +## createRule()
83 +The `createRule(rule)` function will create a new `Rule` in the Hue Bridge.
84 +
85 +* `rule`: The `Rule` that is to be created in the Bridge, consult the documentation on [`Rule` objects](rule.md) to work out how to define a `Rule`
86 +
87 +```js
88 +// You need to have created the myRule instance using code before invoking this
89 +api.rules.createRule(myRule)
90 + .then(result => {
91 + // Will get an instance of a Rule object
92 + console.log(`Created Rule: ${result.toStringDetailed()}`);
93 + })
94 + .catch(err => {
95 + console.error(`Rule was not valid: ${err.message}`);
96 + });
97 +```
98 +
99 +The function will return the created `Rule` object, otherwise will throw an `ApiError`.
100 +
101 +_Note: It is not possible to completely validate all the possible combinations of attributes in a `Rule` as to whether or not
102 +it is valid before trying to create it in the Hue Bridge.
103 +The library will perform a number of checks around eliminating common and obvious issues when building a `Rule`, but
104 +the ultimate check is made by the bridge, but I have seen some very generic error messages in testing when there are
105 +issues in the Rule definition._
106 +
107 +A complete code sample for this function is available [here](../examples/v3/rules/createRule.js).
108 +
109 +
110 +## deleteRule()
111 +The `deleteRule(id)` function will delete the specified rule from the Bridge.
112 +
113 +* `id`: The id for the Rule to remove or the `Rule` instance that you previously obtained from the bridge via a [`getAll()`](#getall) or [`get(id)`](#get) call
114 +
115 +```js
116 +api.rules.deleteRule(id)
117 + .then(result => {
118 + console.log(`Deleted Rule? ${result}`);
119 + });
120 +```
121 +
122 +The function will return `true` upon successful deletion.
123 +
124 +A complete code sample for this function is available [here](../examples/v3/rules/deleteRule.js).
125 +
126 +
127 +
128 +## updateRule()
129 +The `updateRule(rule)` function allows you to modify an existing `Rule` in the Hue Bridge.
130 +
131 +* `rule`: The `Rule` that you wish to update, with the modifications already performed on it, this would have been retrieved previously from the Hue Bridge
132 +
133 +```js
134 +// The rule instance should have been retrieved and modified before calling this code
135 +api.rules.updateRule(rule)
136 + .then(result => {
137 + // show the updated attributes on the rule
138 + console.log(`Updated Rule Attributes: ${JSON.stringify(result)}`);
139 + });
140 +```
141 +
142 +_Note: The library will not perform checks currently against the existing state of the `Rule` on the Bridge and the provided `Rule`
143 +and will update the `name`, `actions` and `conditions` to match the `rule` state passed in._
144 +
145 +The only attributes of an existing `Rule` that you can update currently are:
146 +
147 +* `name`: limited to 32 characters, will be truncated if it exceeds this length
148 +* `actions`: The `RuleAction`s for the Rule, all previous values will be overwritten
149 +* `conditions`: The `RuleCondition`s for the Rule, all previous values will be overwritten
150 +
151 +The function will return a JSON object consisting of the attributes it updated along with a `Boolean` value if the field was updated:
152 +
153 +```js
154 +{
155 + 'name': true,
156 + 'actions': true,
157 + 'conditions': true
158 +}
159 +```
...\ No newline at end of file ...\ No newline at end of file
1 +# Scene
2 +
3 +The Hue Bridge can support two variations of a Scene, `LightScene` and `GroupScene`.
4 +
5 +A Scene is represented as an `id` a `name` and a list of `Lights` stored inside the Hue Bridge. These are separate from
6 +what a scene is in the iOS and Android applications.
7 +
8 +* [Common Scene Properties](#common-scene-properties-and-functions)
9 +* [LightScene](#lightscene)
10 + * [Creating a LightScene](#creating-a-lightscene)
11 + * [Properties](#lightscene-properties)
12 + * [lights](#lights)
13 + * [lightstates](#lightstates)
14 +* [GroupScene](#groupscene)
15 + * [Creating a GroupScene](#creating-a-groupscene)
16 + * [Properties](#groupscene-properties)
17 + * [group](#group-1)
18 + * [lights](#lights-1)
19 + * [lightstates](#lightstates-1)
20 +
21 +
22 +## Common Scene Properties and Functions
23 +Depending upon the properties that you chose to set on the `Scene` the `type` attribute will be implicitly set for you
24 +by the API. This `type` dictates what attributes are modifiable in the Hue Bridge.
25 +
26 +* [id](#id)
27 +* [name](#name)
28 +* [type](#type)
29 +* [owner](#owner)
30 +* [recycle](#recycle)
31 +* [locked](#locked)
32 +* [appdata](#appdata)
33 +* [picture](#picture)
34 +* [lastupdated](#lastupdated)
35 +* [version](#version)
36 +* [toString()](#tostring)
37 +* [toStringDetailed()](#tostringdetailed)
38 +
39 +
40 +### id
41 +Get the `id` for the Scene.
42 +* `get`
43 +
44 +### name
45 +Get/Set a name for the Scene.
46 +* `get`
47 +* `set`
48 +
49 +### type
50 +Get/Set the type of the scene, which is one of `GroupScene` or `LightScene`. Users should not need to set this value,
51 +instead using the `set` on the `group` or `lights` properties instead.
52 +* `get`
53 +* `set`
54 +
55 +### owner
56 +Gets the owner of the Scene.
57 +* `get`
58 +
59 +### recycle
60 +Get/Set the `recyle` attribute of the Scene. This is used to flag scenes that can be automatically deleted by the bridge.
61 +If the `recycle` state is set to `false` the Hue bridge will keep the scene until an application removes it.
62 +* `get`
63 +* `set`
64 +
65 +### locked
66 +Gets the locked state of the Scene. A locked scene means that the scene is in use by the `rule` or `schedule`.
67 +* `get`
68 +
69 +### appdata
70 +Get/Set the associated application data for the scene. This is an `Object` payload that the application is responsible for
71 +any format/encoding/meaning of this data.
72 +
73 +* `get`
74 +* `set`
75 +
76 +When setting this value, you need to create an `Object` with tow keys:
77 +
78 +* `version`: A version for specifying the version on the data object that you are storing.
79 +* `data`: Any data that you wish to store specific to your application, this can be between `0` and `16` characters.
80 +
81 +For example we could store the `location` and `application_name` in the `appdata` using a payload of the form:
82 +
83 +```js
84 +{
85 + version: 1,
86 + data: 'my-custom-app-data'
87 +}
88 +```
89 +
90 +### picture
91 +Get/Set the picture data for the scene. The Hue Bridge does not support setting this via a PUT call which means it is
92 +not possible to update this data field, only at the time of creation.
93 +* `get`
94 +* `set`
95 +
96 +### lastupdated
97 +Gets the last updated time for the Scene.
98 +* `get`
99 +
100 +### version
101 +Gets the version of the Scene
102 +* `get`
103 +
104 +
105 +### toString()
106 +The `toString()` function will obtain a simple `String` representation of the Scene.
107 +
108 +
109 +### toStringDetailed()
110 +The `toStringDetailed()` function will obtain a more detailed representation of the Scene object.
111 +
112 +
113 +
114 +# LightScene
115 +This is the `default` type of `Scene` in the Hue Bridge. It maintains a list of lights that the are associated with the
116 +Scene, which can be updated.
117 +
118 +## Creating a LightScene
119 +You can create a new LightScene object using the `v3.model.createLightScene()` function.
120 +
121 +
122 +## LightScene Properties
123 +The following are the LightScene specific properties above those already defined in the [Common Scene Properties and functions](#common-scene-properties-and-functions).
124 +
125 +### lights
126 +The associated light ids for the `LightScene`.
127 +
128 +* `get`: Obtains the Array of light ids
129 +* `set`: Set the Array of light ids associated with the LightScene
130 +
131 +### lightstates
132 +Gets/Sets the desired LightState for the lights in the scene. This is primarily used to provide some backwards
133 +compatibility in the API with v2, not for normal user usage.
134 +* `get`
135 +* `set`
136 +
137 +_Note: lightStates are only present on scenes that have explicitly been retrieved from the Hue Bridge, that is, scenes
138 +that you have obtained from the `v3.api.scenes.get(id)` API call._
139 +
140 +
141 +
142 +
143 +# GroupScene
144 +A `GroupScene` is a `Scene` with a `type` of `GroupScene`. These scenes are linked to an specified Group in the Hue Bridge.
145 +
146 +The associated lights for the `GroupScene` is controlled via the `Group`. When the `Group` becomes empty or is removed
147 +from the Bridge, the associated `GroupScene`s are also removed.
148 +
149 +The lights for a GroupScene are not modifiable as they belong to the `Group` object.
150 +
151 +
152 +## Creating a GroupScene
153 +You can create a new GroupScene object using the `v3.model.createGroupScene()` function.
154 +
155 +
156 +## GroupScene Properties
157 +The following are the LightScene specific properties above those already defined in the [Common Scene Properties and functions](#common-scene-properties-and-functions).
158 +
159 +### group
160 +The group ID for the GroupScene if associated with a group.
161 +* `get`
162 +* `set`
163 +
164 +### lights
165 +The associated light ids for the `GroupScene`. This is controlled via the membership of the lights in the `Group` that
166 +the GroupScene is associated with.
167 +
168 +* `get`: Obtains the Array of light ids in the target Group
169 +
170 +### lightstates
171 +Gets the LightStates for the lights in the GroupScene. This is primarily used to provide some backwards
172 +compatibility in the API with v2, not for normal user usage.
173 +* `get`
174 +
175 +_Note: lightStates are only present on scenes that have explicitly been retrieved from the Hue Bridge, that is, scenes
176 +that you have obtained from the `v3.api.scenes.get(id)` API call._
1 +# Scenes API
2 +
3 +The `scenes` API provides a means of interacting with the scenes in Hue Bridge.
4 +
5 +The Scenes API interacts with specific [`Scene`](./scene.md) objects stored in the Hue Bridge. These are not to be
6 +confused with the preset scenes that are present in the Android and iOS Hue applications.
7 +
8 +There are a number of limitations on Scenes in the Hue Bridge.
9 +* The bridge can support up to 200 Scenes
10 +* There is a maximum of 2048 Scene LightStates which may lower the maximum number of Scenes that can be stored
11 +
12 +For example if you have 20 LightStates stored on each Scene, the maximum number of Scenes that can be stored in the
13 +Bridge will be 102.
14 +
15 +
16 +* [getAll()](#getall)
17 +* [getScene(id)](#getscene)
18 +* [getSceneByName(name)](#getscenebyname)
19 +* [createScene()](#createscene)
20 +* [updateScene()](#updatescene)
21 +* [updateLightState()](#updatelightstate)
22 +* [deleteScene()](#deletescene)
23 +* [activateScene](#activatescene)
24 +
25 +
26 +## getAll()
27 +The `getAll()` function allows you to get all the scenes that the Hue Bridge has registered with it.
28 +
29 +```js
30 +api.scenes.getAll()
31 + .then(allScenes => {
32 + // Display the Scenes from the bridge
33 + console.log(JSON.stringify(allScenes, null, 2));
34 + });
35 +```
36 +
37 +This function call will resolve to an `Array` of `Scene` objects.
38 +
39 +A complete code sample for this function is available [here](../examples/v3/scenes/getAllScenes.js).
40 +
41 +
42 +
43 +## getScene()
44 +The `getScene(id)` function allows a specific scene to be retrieved from the Hue Bridge.
45 +
46 +* `id`: The `String` id of the scene to retrieve or a previous `Scene` instance obtained from the bridge.
47 +
48 +
49 +```js
50 +api.scenes.getScene('GfOL56sqKPGmPer')
51 + .then(scene => {
52 + console.log(scene.toStringDetailed());
53 + })
54 +;
55 +```
56 +
57 +This function call will resolve to a `Scene` object for the specified scene `id`.
58 +
59 +If the Scene cannot be found an `ApiError` will be returned with a `getHueErrorType()` value of `3`.
60 +
61 +A complete code sample for this function is available [here](../examples/v3/scenes/getScene.js).
62 +
63 +
64 +
65 +## getSceneByName()
66 +The `getSceneByName(name)` function will find all the scenes that are stored in the bridge with the specified `name`.
67 +
68 +* `name`: The `String` that represents the name of the `Scene`s that you wish to find.
69 +
70 +```js
71 +api.scenes.getSceneByName('Concentrate')
72 + .then(results => {
73 + // Do something with the scenes we found
74 + results.forEach(scene => {
75 + console.log(scene.toStringDetailed());
76 + });
77 + })
78 +;
79 +```
80 +
81 +The function will resolve to an `Array` of `Scene` Objects that were matched to the specified `name`.
82 +
83 +A complete code sample for this function is available [here](../examples/v3/scenes/getSceneByName.js).
84 +
85 +
86 +
87 +## createScene()
88 +The `createScene(scene)` function allows for the creation of new `Scene`s in the Hue Bridge.
89 +
90 +* `scene`: A `Scene` object that has been configured with the desired settings for the scene being created.
91 +
92 +```js
93 +const scene = v3.model.createLightScene();
94 +scene.name = 'My Scene';
95 +scene.lights = [1, 2, 3];
96 +
97 +api.scenes.createScene(scene)
98 + .then(scene => {
99 + console.log(`Successfully created scene\n${scene.toStringDetailed()}`);
100 + })
101 +;
102 +```
103 +
104 +The function will resolve with a corresponding `GroupScene` or `LightScene` object, depending upon what was passed in.
105 +
106 +_Note: Whilst the Hue API itself will allow a scene to be updated via creation call, this library will prevent such a
107 +thing, by removing any `id` value from the `Scene` object to prevent overwriting an existing `Scene`.
108 +
109 +A complete code sample for this function is available [here](../examples/v3/scenes/createScene.js).
110 +
111 +
112 +
113 +## updateScene()
114 +The `update(scene)` function allows you to update an existing `Scene` in the Hue Bridge.
115 +
116 +* `scene`: The `Scene` object that contains the relevant updated data to apply to the existing scene.
117 +
118 +```js
119 +// The scene would have be retrieved from the bridge using some other call.
120 +const scene;
121 +scene.name = 'Updated scene name';
122 +
123 +api.scenes.updateScene(scene)
124 + .then(updated => {
125 + console.log(`Updated scene properties: ${JSON.stringify(updated)}`);
126 + })
127 +;
128 +```
129 +
130 +The function will resolve to an object that contains the attribute names of the scene that were updated set tot he success
131 +status of the change to the attribute.
132 +
133 +For example, the result from the above example would resolve to:
134 +
135 +```js
136 +{
137 + "name": true
138 +}
139 +```
140 +
141 +A complete code sample for this function is available [here](../examples/v3/scenes/updateScene.js).
142 +
143 +
144 +
145 +## updateLightState()
146 +The `updateLightState(id, lightId, lightstate)` function allows you to update the LightState stored for a specific light
147 +in a `Scene`.
148 +
149 +* `id`: The `String` id for the Scene to update
150 +* `lightId`: The `Integer` id value for the Light in the Scene to update the LightState of
151 +* `lightstate`: The `SceneLightState` object containing the desired state for the specified light to activate when the
152 + scene is activated.
153 +
154 +_Note: The `SceneLightState` is a simplified `LightState` object and can be imported using:_
155 +```js
156 +const SceneLightState = require('node-hue-api').v3.lightStates.SceneLightState;
157 +```
158 +
159 +```js
160 +const sceneLightState = new SceneLightState();
161 +sceneLightState.on().brightness(100)
162 +
163 +api.scenes.updateLightState(sceneId, lightId, sceneLightState)
164 + .then(results => {
165 + // Show the resultant updated attributes that were modified from the update request
166 + console.log(`Updated LightState values in scene:`)
167 + console.log(JSON.stringify(results, null, 2));
168 + })
169 +;
170 +```
171 +
172 +The function will resolve to an `Object` that contains the `SceneLightState` values that were updated along with the
173 +success state of the requested change.
174 +
175 +For example if you passed a `SceneLightState` that updated the `on` and `bri` attributes you would get a result object of the form:
176 +
177 +```js
178 +{
179 + "on": true,
180 + "bri": true
181 +}
182 +```
183 +
184 +A complete code sample for this function is available [here](../examples/v3/scenes/updateSceneLightState.js).
185 +
186 +
187 +## deleteScene()
188 +The `deleteScene(id)` function will delete the specified scene identified by the `id` from the Hue Bridge.
189 +
190 +* `id`: The `id` of the Scene or a `Scene` instance to delete from the Hue Bridge.
191 +
192 +```js
193 +api.scenes.deleteScene('abc170f')
194 + .then(result => {
195 + console.log(`Deleted scene? ${result}`);
196 + })
197 +;
198 +```
199 +
200 +The call will resolve to a `Boolean` indicating the success status of the deletion.
201 +
202 +A complete code sample for this function is available [here](../examples/v3/scenes/deleteScene.js).
203 +
204 +
205 +## activateScene()
206 +The `activateScene(id)` function allows you to activate an existing stored `Scene`.
207 +
208 +* `id`: The id of the `Scene` to be activated.
209 +
210 +```js
211 +api.scenes.activateScene('GfOL56sqKPGmPer')
212 + .then(activated => {
213 + console.log(`The Scene was successfully activated? ${activated}`);
214 + })
215 +;
216 +```
217 +
218 +The function call will resolve to a `Boolean` indicating the success state for the activation of the `Scene`.
219 +
220 +_Note: Scene activation is really a feature of the [Groups API](./groups.md), not the underlying Scenes API that the
221 +bridge provides. This function is provided as a convenience function._
222 +
223 +See the [Groups API](./groups.md#activating-a-scene) for more details on activating a `Scene`.
...\ No newline at end of file ...\ No newline at end of file
1 +# Schedules API
2 +
3 +The `schedules` API provides a means of interacting with the `Schedule`s in the Hue Bridge.
4 +
5 +The Schedules API interacts with [`Schedule`](./schedule.md) objects along with their associated
6 +[Time Patterns](./timePatterns.md).
7 +
8 +
9 +* [getAll()](#getall)
10 +* [getSchedule(id)](#getschedule)
11 +* [getScheduleByName(name)](#getschedulebyname)
12 +* [createSchedule()](#createschedule)
13 +* [updateSchedule()](#updateschedule)
14 +* [deleteSchedule()](#deleteschedule)
15 +
16 +
17 +## getAll()
18 +The `getAll()` function allows you to get all the `Schedule`s that the Hue Bridge has registered with it.
19 +
20 +```js
21 +api.schedules.getAll()
22 + .then(allSchedules => {
23 + // Display the Schedules from the bridge
24 + allSchedules.forEach(schedule => {
25 + console.log(schedule.toStringDetailed());
26 + });
27 + });
28 +```
29 +
30 +This function call will resolve to an `Array` of `Schedule` objects.
31 +
32 +A complete code sample for this function is available [here](../examples/v3/schedules/getAllSchedules.js).
33 +
34 +
35 +
36 +## getSchedule()
37 +The `getSchedule(id)` function allows a specific `Schedule` to be retrieved from the Hue Bridge.
38 +
39 +* `id`: The `id` of the `Schedule` or a `Schedule` instance that was previously obtained from the bridge.
40 +
41 +
42 +```js
43 +api.schedules.getSchedule(1)
44 + .then(schedule => {
45 + console.log(schedule.toStringDetailed());
46 + })
47 +;
48 +```
49 +
50 +This function call will resolve to a `Schedule` object for the specified schedule `id`.
51 +
52 +If the Scene cannot be found an `ApiError` will be returned with a `getHueErrorType()` value of `3`.
53 +
54 +A complete code sample for this function is available [here](../examples/v3/schedules/getScheduleById.js).
55 +
56 +
57 +
58 +## getScheduleByName()
59 +The `getScheduleByName(name)` function will find all the `Schedule`s that are stored in the bridge with the specified `name`.
60 +
61 +* `name`: The `String` that represents the name of the `Schedules`s that you wish to find.
62 +
63 +```js
64 +api.schedules.getScheduleByName('Wake Up')
65 + .then(results => {
66 + // Do something with the schedules we matched
67 + results.forEach(scene => {
68 + console.log(schedule.toStringDetailed());
69 + });
70 + })
71 +;
72 +```
73 +
74 +The function will resolve to an `Array` of `Schedule` Objects that were matched to the specified `name`. It none are
75 +matched the `Array` will be empty.
76 +
77 +A complete code sample for this function is available [here](../examples/v3/schedules/getSchedulesByName.js).
78 +
79 +
80 +
81 +## createSchedule()
82 +The `createSchedule(schedule)` function allows for the creation of new `Schedule`s in the Hue Bridge.
83 +
84 +* `schedule`: A `Schedule` object that has been configured with the desired settings for the `Schedule` being created.
85 +
86 +```js
87 +const model = require('node-hue-api').v3.model;
88 +
89 +const schedule = model.createSchedule();
90 +schedule.name = 'My Schedule';
91 +schedule.description = 'A test schedule from the node-hue-api examples';
92 +// trigger the schedule in 1 hour from now
93 +schedule.localtime = model.timePatterns.createTimer().hours(1);
94 +// Turn all the lights off (using light group 0 for all lights)
95 +schedule.command = model.actions.group(0).withState(new model.lightStates.GroupLightState().off());
96 +
97 +api.schedules.createSchedule(schedule)
98 + .then(createdSchedule => {
99 + console.log(`Successfully created Schedule\n${createdSchedule.toStringDetailed()}`);
100 + })
101 +;
102 +```
103 +
104 +The function will return a Promise that will resolve with a corresponding `Schedule` with a populated `id` attribute.
105 +
106 +A complete code sample for this function is available [here](../examples/v3/schedule/createSchedule.js).
107 +
108 +
109 +
110 +## updateSchedule()
111 +The `updateSchedule(schedule)` function will update the schedule in the bridge to match the attributes of the specified
112 +schedule.
113 +
114 +* `schedule`: The schedule with updated attributes to set on the bridge.
115 +
116 +```js
117 +// Obtain a schedule from the Bridge, e.g. get schedule with id = 1
118 +const mySchedule = await hue.schedules.get(1);
119 +
120 +// Update some attributes
121 +mySchedule.name = 'Updated Name';
122 +
123 +// Update the schedule in the bridge
124 +hue.schedules.updateSchedule(mySchedule)
125 + .then(updateResult => {
126 + console.log(`Updated Name? ${updateResult.name}`); // Will print "Updated Name? true"
127 + });
128 +```
129 +
130 +_Note: Currently there is no checking as to whether or not a value has been modified, so all the updatable attributes are
131 +passed to the bridge. (this is quicker and more efficient than doing a get/put chain of requests)._
132 +
133 +The function call will return a `Promise` that will resolve to an `Object` with the update information.
134 +
135 +The result Object that will have the form of the keys that were updated along with a boolean flag
136 +indicating if the value was modified.
137 +```js
138 +{
139 + "name": true,
140 + "description": true,
141 + "command": true,
142 + "localtime": true,
143 + "status": true,
144 + "autodelete": true
145 +}
146 +```
147 +
148 +A complete code sample for this function is available [here](../examples/v3/schedule/updateSchedule.js).
149 +
150 +
151 +
152 +## deleteSchedule()
153 +The `deleteSchedule(id)` function will delete the specified scene identified by the `id` from the Hue Bridge.
154 +
155 +* `id`: The `id` of the scene to delete from the Hue Bridge.
156 +
157 +```js
158 +api.scenes.delete('abc170f')
159 + .then(result => {
160 + console.log(`Deleted scene? ${result}`);
161 + })
162 +;
163 +```
164 +
165 +The call will resolve to a `Boolean` indicating the success status of the deletion.
166 +
167 +A complete code sample for this function is available [here](../examples/v3/scenes/deleteScene.js).
...\ No newline at end of file ...\ No newline at end of file
1 +# Sensor
2 +
3 +The Hue Bridge can support a number of sensors. The API has various objects for each of the types of Sensors that the
4 +Hue Bridge can support.
5 +
6 +Some of these Sensors are Hardware sensors whilst others are Software constructs that can be updated by API calls.
7 +
8 +The sensors that can be built and controlled via software are the `CLIP` variety.
9 +
10 +The API provides access to the Sensor objects via the [`v3.api.sensors` API](sensors.md), but you can also create new
11 +CLIP Sensor objects using the various CLIP sensor classes by using the `v3.model.createCLIP[xxx]Sensor()` functions.
12 +
13 +
14 +- [CLIP Sensors](#clipsensors)
15 + - [CLIP GenericFlag](#clipgenreicflag)
16 + - [CLIP GenericStatus](#clipgenericstatus)
17 + - [CLIP Humidity](#cliphumidity)
18 + - [CLIP LightLevel](#cliplightlevel)
19 + - [CLIP OpenClose](#clipopenclose)
20 + - [CLIP Presence](#clippresence)
21 + - [CLIP Switch](#clipswitch)
22 + - [CLIP Temperature](#cliptemperature)
23 +
24 +
25 +
26 +## CLIP Sensors
27 +
28 +CLIP Sensors allow you to integrate external objects and statuses into the Hue Bridge via CLIP Sensors.
29 +
30 +For example you may have the ability to detect the humidity in a room and want to store this value in the Hue Bridge.
31 +You can do this using a `CLIPHumidity` Sensor which can be saved and then updated in the Hue Bridge upon changes.
32 +
33 +All sensors have the following mandatory properties:
34 +
35 +* `type`: This is the type of sensor, this is readable and only set at the time of instantiation of the object
36 +* `modelid`: A model ID for the sensor which should uniquely identify the hardware model oif the device from the manufacturer
37 +* `manufacturername`: The manufacturer name of the sensor
38 +* `uniqueid`: A unique ID for the sensor, this should be the MAC Address of the device
39 +* `swversion`: A software version running on the sensor
40 +* `name`: A name for the sensor which will be the human readable name
41 +
42 +The above properties have to be set when creating a new sensor from scratch in code, except for `name` which can be
43 +modified after creation.
44 +
45 +All CLIP Sensors also have the following properties:
46 +
47 +* `id`: A readonly value for the `id` that the Hue Bridge will assign to a Sensor
48 +* `lastupdated`: A readonly timestamp value when the sensor was last updated in the Hue Bridge
49 +* `on`: `get` and `set`, turns the sensor on/off. When off, state changes of the sensor are not reflected in the sensor resource
50 +* `reachable`: `get` and `set`, indicates whether communication with the device is possible
51 +* `battery`: `get` and `set`, the current battery state in percent for battery powered devices
52 +* `url`: `get` and `set`, an optional URL to the CLIP sensor
53 +
54 +
55 +
56 +### CLIPGenericFlag
57 +The `CLIPGenericFlag` sensor is a `Boolean` flag sensor.
58 +
59 +A generic sensor object for 3rd party IP sensor use.
60 +E.g. the portal can make use of a Generic sensor to indicate IFTTT events.
61 +
62 +
63 +The unique properties for the GenericFlag Sensor are:
64 +
65 +* `flag`: `get` and `set` stores a `Boolean` state
66 +
67 +
68 +Creating a `CLIPGenericFlag` sensor can be done as shown below:
69 +```js
70 +const model = require('node-hue-api').v3.model;
71 +
72 +const mySensor = model.createCLIPGenericFlagSensor();
73 +mySensor.modelid = 'software';
74 +mySensor.swversion = '1.0';
75 +mySensor.uniqueid = '00:00:00:01';
76 +mySensor.manufacturername = 'node-hue-api';
77 +
78 +// Set the name of the sensor
79 +mySensor.name = 'My awesome clip generic flag sensor';
80 +
81 +// Set the flag state to true
82 +mySensor.flag = true;
83 +```
84 +
85 +A complete code sample for sensors is available [here](../examples/v3/sensors/creatingClipSensors.js).
86 +
87 +
88 +
89 +### CLIPGenericStatus
90 +The `CLIPGenericStatus` sensor is a `Integer` value sensor.
91 +
92 +A generic sensor object for 3rd party IP sensor use.
93 +E.g. the portal can make use of a Generic sensor to indicate IFTTT events.
94 +
95 +
96 +The unique properties for the `GenericFlag` Sensor are:
97 +
98 +* `status`: `get` and `set`, stores an integer value
99 +
100 +
101 +Creating a `CLIPGenericStatus` sensor can be done as shown below:
102 +```js
103 +const model = require('node-hue-api').v3.model;
104 +
105 +const mySensor = model.createCLIPGenericStatusSensor();
106 +mySensor.modelid = 'software';
107 +mySensor.swversion = '1.0';
108 +mySensor.uniqueid = '00:00:00:01';
109 +mySensor.manufacturername = 'node-hue-api';
110 +
111 +// Set the name of the sensor
112 +mySensor.name = 'My awesome clip generic status sensor';
113 +// Set the status to 1000
114 +mySensor.status = 1000;
115 +```
116 +
117 +A complete code sample for sensors is available [here](../examples/v3/sensors/creatingClipSensors.js).
118 +
119 +
120 +
121 +
122 +### CLIPHumidity
123 +The `CLIPHumidity` sensor is a sensor measuring the current ambient humidity.
124 +
125 +The unique properties for the `Humidity` Sensor are:
126 +
127 +* `humidity`: `get` and `set`, the ambient humidity in 0.01% steps, e.g. 2000 = 20%
128 +
129 +Creating a `CLIPHumidity` sensor can be done as shown below:
130 +```js
131 +const model = require('node-hue-api').v3.model;
132 +
133 +const mySensor = model.createCLIPHumiditySensor();
134 +mySensor.modelid = 'software';
135 +mySensor.swversion = '1.0';
136 +mySensor.uniqueid = '00:00:00:01';
137 +mySensor.manufacturername = 'node-hue-api';
138 +
139 +// Set the name of the sensor
140 +mySensor.name = 'Lounge Humidity';
141 +// Set the humidity level
142 +mySensor.humidity = 1000; // 10%
143 +```
144 +
145 +A complete code sample for sensors is available [here](../examples/v3/sensors/creatingClipSensors.js).
146 +
147 +
148 +
149 +
150 +### CLIPLightLevel
151 +The `CLIPLightLevel` sensor indicates the ambient light level at the sensor location.
152 +
153 +The unique properties for the `Lighlevel` Sensor are:
154 +
155 +* `tholddark`: `get` and `set`, threshold used in rules to determine insufficient light level, below threshold, between `0` and `65535`
156 +* `tholdoffset`: `get` and `set`, threshold used in riles to determine sufficient light level, above threshold, between `0` and `65535`
157 +* `lightlevel`: `get` and `set`, light level in `10000 log10 (lux) + 1` value measured by sensor, between `0` and `65535`
158 +* `dark`: `get` and `set`, `Boolean` indicating light level is at or below given dark threshold, between `0` and `65535`
159 +* `daylight`: `get` and `set`, `Boolean` indicating light level is at or above light threshold (dark + offset), between `0` and `65535`
160 +
161 +Creating a `CLIPLightLevel` sensor can be done as shown below:
162 +```js
163 +const model = require('node-hue-api').v3.model;
164 +
165 +const mySensor = model.createCLIPLightlevelSensor();
166 +mySensor.modelid = 'software';
167 +mySensor.swversion = '1.0';
168 +mySensor.uniqueid = '00:00:00:01';
169 +mySensor.manufacturername = 'node-hue-api';
170 +
171 +// Set the name of the sensor
172 +mySensor.name = 'Lounge LightLevel';
173 +// Set the light level
174 +mySensor.lightlevel = 1000;
175 +```
176 +
177 +A complete code sample for sensors is available [here](../examples/v3/sensors/creatingClipSensors.js).
178 +
179 +
180 +
181 +### CLIPOpenClose
182 +The `CLIPOpenClose` sensor is for open/close status sensors, like a door or window.
183 +
184 +The unique properties for the `OpenClose` Sensor are:
185 +
186 +* `open`: `get` and `set`, boolean indicating open state
187 +
188 +
189 +Creating a `CLIPOpenClose` sensor can be done as shown below:
190 +```js
191 +const model = require('node-hue-api').v3.model;
192 +
193 +const mySensor = model.createCLIPOpenCloseSensor();
194 +mySensor.modelid = 'software';
195 +mySensor.swversion = '1.0';
196 +mySensor.uniqueid = '00:00:00:01';
197 +mySensor.manufacturername = 'node-hue-api';
198 +
199 +// Set the name of the sensor
200 +mySensor.name = 'Lounge Door';
201 +// Set the open state
202 +mySensor.open = false;
203 +```
204 +
205 +A complete code sample for sensors is available [here](../examples/v3/sensors/creatingClipSensors.js).
206 +
207 +
208 +
209 +### CLIPPresence
210 +The `CLIPPresense` sensor is for registering the presence of someone at the location of the sensor.
211 +
212 +The unique properties for the `Presense` Senor are:
213 +
214 +* `presence`: `get` and `set`, boolean indicating if there is a presence at the sensor
215 +
216 +
217 +Creating a `CLIPPresence` sensor can be done as shown below:
218 +```js
219 +const model = require('node-hue-api').v3.model;
220 +
221 +const mySensor = model.createCLIPPresenceSensor();
222 +mySensor.modelid = 'software';
223 +mySensor.swversion = '1.0';
224 +mySensor.uniqueid = '00:00:00:01';
225 +mySensor.manufacturername = 'node-hue-api';
226 +
227 +// Set the name of the sensor
228 +mySensor.name = 'Lounge Presence';
229 +// Set the presence state
230 +mySensor.presence = true;
231 +```
232 +
233 +A complete code sample for sensors is available [here](../examples/v3/sensors/creatingClipSensors.js).
234 +
235 +
236 +
237 +### CLIPSwitch
238 +The `CLIPSwitch` sensor is for registering switch button states.
239 +
240 +The unique properties for the `Switch` Sensor are:
241 +
242 +* `buttonevent`: `get` and `set`, an integer value indicating the button event that has been triggered on the switch.
243 +
244 +In Zigbee switches the events relate to the individual buttons that are present on the switch and the state triggered on
245 +the last button pressed/released an whether it was a short or long press.
246 +
247 +Creating a `CLIPSwitch` sensor can be done as shown below:
248 +```js
249 +const model = require('node-hue-api').v3.model;
250 +
251 +const mySensor = model.createCLIPSwitchSensor();
252 +mySensor.modelid = 'software';
253 +mySensor.swversion = '1.0';
254 +mySensor.uniqueid = '00:00:00:01';
255 +mySensor.manufacturername = 'node-hue-api';
256 +
257 +// Set the name of the sensor
258 +mySensor.name = 'Lounge Wall Switch';
259 +// Set a button event code state
260 +mySensor.buttonevent = 2000;
261 +```
262 +
263 +A complete code sample for sensors is available [here](../examples/v3/sensors/creatingClipSensors.js).
264 +
265 +
266 +
267 +### CLIPTemperature
268 +The `CLIPTemperature` sensor is for measuring current ambient temperature.
269 +
270 +The unique properties for the `Temperature` Sensor are:
271 +
272 +* `temperature`: `get` and `set`, the current temperature in 0.01 degrees celsius, e.g. 3000 is 30.00 degrees
273 +
274 +
275 +Creating a `CLIPTemperature` sensor can be done as shown below:
276 +```js
277 +const model = require('node-hue-api').v3.model;
278 +
279 +const mySensor = model.createCLIPTemperatureSensor();
280 +mySensor.modelid = 'software';
281 +mySensor.swversion = '1.0';
282 +mySensor.uniqueid = '00:00:00:01';
283 +mySensor.manufacturername = 'node-hue-api';
284 +
285 +// Set the name of the sensor
286 +mySensor.name = 'Lounge Temperature';
287 +// Set a the temperature to 18.5 degrees
288 +mySensor.buttonevent = 1850;
289 +```
290 +
291 +A complete code sample for sensors is available [here](../examples/v3/sensors/creatingClipSensors.js).
...\ No newline at end of file ...\ No newline at end of file
1 +# Sensors API
2 +
3 +The sensors API allows you to interact with the sensors features of the Hue Bridge.
4 +
5 +* [Sensor Objects](#sensors)
6 +* [getAll()](#getall)
7 +* [getSensor(id)](#getsensor)
8 +* [searchForNew()](#searchfornew)
9 +* [getNew()](#getnew)
10 +* [renameSensor(sensor)](#renamesensor)
11 +* [updateName()](#updatename)
12 +* [createSensor(sensor)](#createsensor)
13 +* [deleteSensor(id)](#deletesensor)
14 +* [updateSensorConfig(sensor)](#updatesensorconfig)
15 +* [updateSensorState(sensor)](#updatesensorstate)
16 +
17 +
18 +## Sensors
19 +
20 +There are many different types of `Sensors` that can exist in a Hue Bridge. Some of these are actual Physical Sensors
21 +and others can be Programmable `CLIP` Sensors.
22 +
23 +Consult the documentation for the `CLIP Sensors` [here](sensor.md).
24 +
25 +
26 +
27 +## getAll()
28 +This function allows you to retrieve all the sensors that are stored in the Hue Bridge.
29 +
30 +```js
31 +api.sensors.getAll()
32 + .then(allSensors => {
33 + // Display the details of the sensors we got back
34 + console.log(JSON.stringify(allSensors, null, 2));
35 + })
36 +;
37 +```
38 +
39 +This will return an Array of `Sensor` objects that exist in the Hue Bridge.
40 +
41 +A complete code sample for getting all sensors is available [here](../examples/v3/sensors/getAllSensors.js).
42 +
43 +
44 +
45 +## getSensor()
46 +The `getSensor(id)` function will obtain the sensor identified by the specified `id` value.
47 +
48 +```js
49 +// Get the daylight sensor for the bridge, at id 1
50 +api.sensors.getSensor(1)
51 + .then(sensor => {
52 + console.log(sensor.toStringDetailed());
53 + })
54 +;
55 +```
56 +
57 +The Sensor that is returned will be an instance of `Sensor` or one of the many specializations that the bridge supports.
58 +See [here](#sensors) for more details.
59 +
60 +A complete code sample is available [here](../examples/v3/sensors/getSensor.js).
61 +
62 +
63 +
64 +## searchForNew()
65 +The `searchForNew()` function will initiate a search for new sensors.
66 +
67 +```js
68 +api.sensors.searchForNew()
69 + .then(result => {
70 + console.log(`Initiated search for new sensors? ${result}`);
71 + })
72 +;
73 +```
74 +
75 +A `Boolean` result is returned indicating the success state of starting a search.
76 +
77 +A complete code sample is available [here](../examples/v3/sensors/searchForNew.js).
78 +
79 +
80 +
81 +## getNew()
82 +The `getNew()` function will return the new sensors that were discovered in the previous search for new sensors.
83 +
84 +```js
85 +api.sensors.getNew()
86 + .then(result => {
87 + // Show the time of the last scan
88 + console.log(`Last Scan Performed: ${result.lastscan}`);
89 + // Display the new sensors
90 + console.log(`Sensors found:\n${JSON.stringify(result.sensors, null, 2)}`);
91 + })
92 +;
93 +```
94 +
95 +The return `Object` has the following properties:
96 +
97 +* `lastscan`: The timestamp of the last search
98 +* `sensors`: An `Array` of the sensors that were discovered in the last search
99 +
100 +A complete code sample is available [here](../examples/v3/sensors/getNewSensors.js).
101 +
102 +
103 +## renameSensor()
104 +The `renameSensor(sensor)` function will allow you to rename an existing Sensor in the Hue Bridge.
105 +
106 +The parameters are:
107 +
108 +* `sensor`: The updated `Sensor` object with the changed name.
109 +
110 +```js
111 +// The sensor would have been previously obtained from the bridge.
112 +sensor.name = 'Updated Sensor Name';
113 +
114 +api.sensors.renameSensor(sensor)
115 + .then(result => {
116 + console.log(`Updated Sensor Name? ${result}`)
117 + });
118 +```
119 +
120 +The result from the function call will be a `Boolean` indicating the success status of the renaming action.
121 +
122 +A complete code sample is available [here](../examples/v3/sensors/renameSensor.js).
123 +
124 +
125 +## updateName()
126 +The `updateName(id, name)` function will allow you to rename an existing Sensor in the Hue Bridge.
127 +This has been deprecated, use [`reanmeSesnor(sensor)`](#renamesensor) instead.
128 +
129 +
130 +## createSensor()
131 +The `createSensor(sensor)` function allows you to create software backed `CLIP` sensors.
132 +
133 +For details on creating the various types of sensors that the Hue Bridge supports, consult the [sensor](sensor.md)
134 +documentation or the [example code](../examples/v3/sensors/creatingClipSensors.js)
135 +
136 +```js
137 +api.sensors.createSensor(sensor)
138 + .then(sensor => {
139 + console.log(`Created sensor\n${sensor.toStringDetailed()}`)
140 + })
141 +```
142 +
143 +The promise will resolve to an instance of a `Sensor` that will be an instance of the type of sensor data that you
144 +passed in. e.g. a `CLIPOpenClose` sensor.
145 +
146 +A complete code sample is available [here](../examples/v3/sensors/createNewSensor.js).
147 +
148 +
149 +## deleteSensor()
150 +The `deleteSensor(id)` function allows you to delete a sensor with the specified `id`.
151 +
152 +* `id`: The id of the `Sensor` or the `Sensor` itself to be deleted from the Bridge.
153 +
154 +```js
155 +api.sensors.deleteSensor(sensorIdToRemove)
156 + .then(result => {
157 + console.log(`Sensor deleted? ${result}`);
158 + })
159 + .catch(err => {
160 + if (err.getHueErrorType() === 3) {
161 + console.log(`Sensor was not found`);
162 + } else {
163 + console.error(`Unexpected Error: ${err.message}`);
164 + }
165 + })
166 +;
167 +```
168 +
169 +The function call will return a `Boolean` with the success status of the deletion of the specified sensor. If the Sensor
170 +is not found in the bridge, an `ApiError` will be thrown.
171 +
172 +A complete code sample is available [here](../examples/v3/sensors/deleteSensor.js).
173 +
174 +
175 +
176 +## updateSensorConfig()
177 +The `updateSensorConfig(sensor)` function will update the `Sensor`s `config` attributes on the Hue Bridge.
178 +
179 +* `sensor`: The `Sensor` from the bridge with the `config` attributes updated to the desired state.
180 +
181 +```js
182 +api.sensors.updateSensorConfig(sensor)
183 + .then(result => {
184 + console.log(`Updated sensor config? ${result}`);
185 + })
186 +```
187 +
188 +_Note: The config attributes differ depending upon the type of Sensor that you are dealing with. To identify what
189 +`config` attributes are available you can get the Sensor from the Hue Bridge and use the `.toStringDetailed()` function
190 +on it to show the `config` attributes for that `Sensor`._
191 +
192 +The function will resolve to a `Boolean` indicating the successful updating of the config values.
193 +
194 +
195 +
196 +## updateSensorState()
197 +The `updateSensorState(sensor)` function allows you to update a `CLIPSensor`s state using the current state of the provided
198 +sensor object.
199 +
200 +* `sensor`: The `Sensor` object with the updated state values to be stored. You can get the Sensor by retrieving it
201 +from the Hue Bridge via a [`get(id)`](#get) or [`getAll()`](#getall) call.
202 +
203 +```js
204 +api.sensors.updateSensorState(mySensor)
205 + .then(result => {
206 + console.log(`Sensor Updated? ${result}`);
207 + });
208 +```
209 +
210 +The function will resolve to a `Object` with the keys being the state values that were attempted to be updated and the
211 +value set to a `Boolean` indicating if the bridge updated the value.
212 +
213 +For example for an OpenClose `Sensor` it would return the following object (as it only has a state of `open`):
214 +```json
215 +{
216 + "open": true
217 +}
218 +```
219 +
220 +_Note: This will only work for CLIP `Sensor` types as other sensor types are usually hardware devices. Each type of
221 +sensor has different state attributes that can be modified. Consult the [`Sensor` documentation](./sensor.md) for the
222 +state attributes for the sensor type that you are interacting with._
223 +
224 +A complete code sample is available [here](../examples/v3/sensors/updateSensorState.js).
...\ No newline at end of file ...\ No newline at end of file
This diff is collapsed. Click to expand it.
1 +# Users API
2 +
3 +The `users` API provides a means of interacting with the Hue Bridge user accounts.
4 +
5 +* [User Names](#user-names)
6 +* [createUser(appName, deviceName)](#createuser)
7 +* [deleteUser(username)](#deleteuser)
8 +* [getAll()](#getAll)
9 +* [get(username)](#get)
10 +* [getByName(appName, deviceName)](#getbyname)
11 +
12 +
13 +## User Names
14 +The names of user accounts that are created in the bridge consist of two variations:
15 +
16 +* Single string value `0..40 charcters`
17 +* Application Name and Device Name combination format `<applicaiton_name>#<device_name>`
18 + * `application_name`: `0..20 characters`
19 + * `device_name`: `0..19 characters`
20 +
21 +The bridge APIs now encourage the use of the latter format and this is the primary format that this API will encourage
22 +on the creation of new accounts.
23 +
24 +
25 +
26 +## createUser
27 +The `createUser(appName, deviceName)` function allows for the creation of new users on the Hue Bridge.
28 +
29 +This function can be invoked without previously authenticating with another user account on the Bridge, but for it to
30 +succeed, it requires the user to press the Link Button on the Bridge, otherwise it will generate an `ApiError` with a
31 +type of `101`.
32 +
33 +Once the user presses the Link Button on the bridge, you have roughly 30 seconds to execute this call to create a new
34 +user.
35 +
36 +The parameters for the function are:
37 +
38 +* `appName`: The application name for the user that is being created, e.g. `node-hue-api`. This has to be a string between 0 and 20 characters
39 +* `devciceName`: The device name for the user that is being created, e.g. `mac-mini`, This has to be a string between 0 and 19 characters
40 +
41 +```js
42 +api.users.createUser('node-hue-api', 'my-device-or-app')
43 + .then(usernameAndKey => {
44 + console.log(`Created User: ${usernameAndKey.username}`);
45 + console.log(`PSK for Entertainment API : ${usernameAndKey.clientkey}`);
46 + })
47 + .catch(err => {
48 + if (err.getHueErrorType() === 101) {
49 + console.error(`The Link Button on the bridge was not pressed. Please press the link button and then re-run.`);
50 + } else {
51 + // Unexpected error
52 + console.error(err);
53 + }
54 + })
55 +;
56 +```
57 +
58 +If successful, this function will resolve to an `Object` for the created user with the following properties:
59 +
60 +* `username`: The `username` to use for authenticating against the bridge
61 +* `clientkey`: PSK Identity that can be used with the Streaming Entertainment API
62 +
63 +_Note that this is sensitive data, this is effectively a password for accessing the bridge, so be sensible about where you store this._
64 +
65 +A complete code sample for creating a user is available [here](../examples/v3/users/createUser.js).
66 +
67 +
68 +
69 +## deleteUser
70 +The `deleteUser(username)` function allows you to remove an existing user from the bridge.
71 +
72 +Note currently as of 28/07/2019 (bridge API version 1.33.0) there are some issues in the Bridge with respect to permissions on the removal of users
73 +that prevents the removal of user accounts.
74 +
75 +
76 +
77 +## getAll
78 +The `getAll()` function will return all the whitelisted users from the Hue bridge.
79 +
80 +The result will always be an `Array` or user objects that are in the Bridge Whitelist which will consist of `Object`s
81 +with the properties returned in the bridge configuration which as of bridge API version `1.20` is:
82 +
83 +* `username`: The username that is used to authenticate the user account against the Bridge
84 +* `name`: The name that was used to create the user account, either a human readable `String` or of the format `<application_name>#<device_name>`
85 +* `create date`: The date of the creation of the user
86 +* `last use date`: The date that the user account was last used
87 +
88 +
89 +```js
90 +api.users.getAll()
91 + .then(allUsers => {
92 + // Do something with the users array
93 + console.log(JSON.stringify(allUsers, null, 2));
94 + })
95 +;
96 +```
97 +
98 +A complete code sample for creating a user is available [here](../examples/v3/users/getAllUsers.js).
99 +
100 +
101 +
102 +## get
103 +The `get(username)` function will return the details for the user account stored in the bridge.
104 +
105 +If the username is found in the bridge, the result will be an object that has the following properties:
106 +
107 +* `username`: The username that is used to authenticate the user account against the Bridge
108 +* `name`: The name that was used to create the user account, either a human readable `String` or of the format `<application_name>#<device_name>`
109 +* `create date`: The date of the creation of the user
110 +* `last use date`: The date that the user account was last used
111 +
112 +```js
113 +api.users.get('username_value')
114 + .then(allUsers => {
115 + // Do something with the users array
116 + console.log(JSON.stringify(allUsers, null, 2));
117 + })
118 +;
119 +```
120 +
121 +A complete code sample for creating a user is available [here](../examples/v3/users/getUser.js).
122 +
123 +
124 +
125 +## getByName
126 +The `getByName(appName, deviceName)` or `getByName(name)` function allowss you to find the user accounts that use the
127 +specified `name` or `appName` and `deviceName` combination
128 +
129 +The result will always be an `Array` or user objects that are in the Bridge Whitelist which will consist of `Object`s
130 +with the properties returned in the bridge configuration which as of bridge API version `1.20` is:
131 +
132 +* `username`: The username that is used to authenticate the user account against the Bridge
133 +* `name`: The name that was used to create the user account, either a human readable `String` or of the format `<application_name>#<device_name>`
134 +* `create date`: The date of the creation of the user
135 +* `last use date`: The date that the user account was last used
136 +
137 +```js
138 +api.users.get('username_value')
139 + .then(allUsers => {
140 + // Do something with the users array
141 + console.log(JSON.stringify(allUsers, null, 2));
142 + })
143 +;
144 +```
145 +
146 +A complete code sample for creating a user is available [here](../examples/v3/users/getUserByName.js).
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const hueApi = require('../../../index');
4 +// If using this code outside of this library the above should be replaced with
5 +// const hueApi = require('node-hue-api');
6 +
7 +// Replace this with your username for accessing the bridge
8 +const USERNAME = require('../../../test/support/testValues').username;
9 +
10 +hueApi.discovery.nupnpSearch()
11 + .then(searchResults => {
12 + const host = searchResults[0].ipaddress;
13 + return hueApi.v3.api.createLocal(host).connect(USERNAME);
14 + })
15 + .then(api => {
16 + return api.capabilities.getAll();
17 + })
18 + .then(capabilities => {
19 + // Display the Capabilities Object Details
20 + console.log(capabilities.toStringDetailed());
21 + })
22 +;
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +// Replace this with your username for accessing the bridge
8 +const USERNAME = require('../../../test/support/testValues').username;
9 +
10 +v3.discovery.nupnpSearch()
11 + .then(searchResults => {
12 + const host = searchResults[0].ipaddress;
13 + return v3.api.createLocal(host).connect(USERNAME);
14 + })
15 + .then(api => {
16 + return api.configuration.getAll();
17 + })
18 + .then(config => {
19 + // Display the complete configuration for the Bridge, including lights, sensors, config etc...
20 + console.log(JSON.stringify(config, null, 2));
21 + })
22 +;
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +// Replace this with your username for accessing the bridge
8 +const USERNAME = require('../../../test/support/testValues').username;
9 +
10 +v3.discovery.nupnpSearch()
11 + .then(searchResults => {
12 + const host = searchResults[0].ipaddress;
13 + return v3.api.createLocal(host).connect(USERNAME);
14 + })
15 + .then(api => {
16 + return api.configuration.getConfiguration();
17 + })
18 + .then(config => {
19 + // Display the configuration for the Bridge
20 + console.log(JSON.stringify(config, null, 2));
21 + })
22 +;
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +// Replace this with your username for accessing the bridge
8 +const USERNAME = require('../../../test/support/testValues').username;
9 +
10 +v3.discovery.nupnpSearch()
11 + .then(searchResults => {
12 + const host = searchResults[0].ipaddress;
13 + return v3.api.createLocal(host).connect(USERNAME);
14 + })
15 + .then(api => {
16 + // The JSON payload of the configuration value(s) to update
17 + const valuesToUpdate = {
18 + 'touchlink': true
19 + };
20 +
21 + return api.configuration.updateConfiguration(valuesToUpdate);
22 + })
23 + .then(result => {
24 + // Display the configuration for the Bridge
25 + console.log(`Updated the bridge configuration? ${result}`);
26 + })
27 + .catch(err => {
28 + // If you attempt to update a value that is not modifiable, an ApiError will be generated
29 + // the message will indicate that the parameter is not modifiable.
30 + console.error(err.message)
31 + })
32 +;
1 +const v3 = require('../../index').v3
2 + , discovery = require('../../index').discovery
3 + // If using this code outside of the examples directory, you will want to use the line below and remove the
4 + // const v3 = require('node-hue-api').v3
5 + // const discovery = require('node-hue-api').discovery
6 + , hueApi = v3.api
7 +;
8 +
9 +const appName = 'node-hue-api';
10 +const deviceName = 'example-code';
11 +
12 +
13 +async function discoverBridge() {
14 + const discoveryResults = await discovery.nupnpSearch();
15 +
16 + if (discoveryResults.length === 0) {
17 + console.error('Failed to resolve any Hue Bridges');
18 + return null;
19 + } else {
20 + // Ignoring that you could have more than one Hue Bridge on a network as this is unlikely in 99.9% of users situations
21 + return discoveryResults[0].ipaddress;
22 + }
23 +}
24 +
25 +async function discoverAndCreateUser() {
26 + const ipAddress = await discoverBridge();
27 +
28 + // Create an unauthenticated instance of the Hue API so that we can create a new user
29 + const unauthenticatedApi = await hueApi.createLocal(ipAddress).connect();
30 +
31 + let createdUser;
32 + try {
33 + createdUser = await unauthenticatedApi.users.createUser(appName, deviceName);
34 + console.log('*******************************************************************************\n');
35 + console.log('User has been created on the Hue Bridge. The following username can be used to\n' +
36 + 'authenticate with the Bridge and provide full local access to the Hue Bridge.\n' +
37 + 'YOU SHOULD TREAT THIS LIKE A PASSWORD\n');
38 + console.log(`Hue Bridge User: ${createdUser.username}`);
39 + console.log(`Hue Bridge User Client Key: ${createdUser.clientkey}`);
40 + console.log('*******************************************************************************\n');
41 +
42 + // Create a new API instance that is authenticated with the new user we created
43 + const authenticatedApi = await hueApi.createLocal(ipAddress).connect(createdUser.username);
44 +
45 + // Do something with the authenticated user/api
46 + const bridgeConfig = await authenticatedApi.configuration.getConfiguration();
47 + console.log(`Connected to Hue Bridge: ${bridgeConfig.name} :: ${bridgeConfig.ipaddress}`);
48 +
49 + } catch(err) {
50 + if (err.getHueErrorType() === 101) {
51 + console.error('The Link button on the bridge was not pressed. Please press the Link button and try again.');
52 + } else {
53 + console.error(`Unexpected Error: ${err.message}`);
54 + }
55 + }
56 +}
57 +
58 +// Invoke the discovery and create user code
59 +discoverAndCreateUser();
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const discovery = require('../../index').discovery
4 +// If using this code outside of the examples directory, you will want to use the line below and remove the
5 +// const discovery = require('node-hue-api').discovery
6 +;
7 +
8 +// For this to work properly you need to be connected to the same network that the Hue Bridge is running on.
9 +// It will not function across VLANs or different network ranges.
10 +
11 +async function getBridge() {
12 + try {
13 + const results = await discovery.nupnpSearch();
14 +
15 + // Results will be an array of bridges that were found
16 + console.log(JSON.stringify(results, null, 2));
17 + } catch (err) {
18 + console.log(`Failure with n-UPnP search: ${err.message}`)
19 + }
20 +}
21 +
22 +getBridge();
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const discovery = require('../../index').discovery
4 +;
5 +
6 +async function getBridge() {
7 + const results = await discovery.upnpSearch();
8 +
9 + // Results will be an array of bridges that were found
10 + console.log(JSON.stringify(results, null, 2));
11 +}
12 +
13 +getBridge();
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +const model = v3.model;
8 +
9 +// Replace this with your Bridge User name
10 +const USERNAME = require('../../../test/support/testValues').username;
11 +
12 +
13 +v3.discovery.nupnpSearch()
14 + .then(searchResults => {
15 + const host = searchResults[0].ipaddress;
16 + return v3.api.createLocal(host).connect(USERNAME);
17 + })
18 + .then(api => {
19 + const entertainment = model.createEntertainment();
20 + // The name of the new zone we are creating
21 + entertainment.name = 'Testing Entertainment Creation';
22 + // The array of light ids that will be in the entertainment group, not all lights can be added, they have to support streaming
23 + entertainment.lights = [13, 14];
24 + // The class for the entertainment group, this has to be selected from the valid values, consult the documentation for details
25 + entertainment.class = 'TV';
26 +
27 + return api.groups.createGroup(entertainment)
28 + .then(group => {
29 + console.log(group.toStringDetailed());
30 +
31 + // Delete the new Entertainment Group
32 + return api.groups.deleteGroup(group);
33 + });
34 + })
35 + .catch(err => {
36 + console.error(err);
37 + })
38 +;
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +const model = v3.model;
8 +
9 +// Replace this with your Bridge User name
10 +const USERNAME = require('../../../test/support/testValues').username;
11 +
12 +
13 +v3.discovery.nupnpSearch()
14 + .then(searchResults => {
15 + const host = searchResults[0].ipaddress;
16 + return v3.api.createLocal(host).connect(USERNAME);
17 + })
18 + .then(api => {
19 + const newGroup = model.createLightGroup();
20 + // The name of the new group to create
21 + newGroup.name = 'My New Group';
22 + // The array of light ids that will be in the group
23 + newGroup.lights = [2];
24 +
25 + return api.groups.createGroup(newGroup)
26 + .then(group => {
27 + console.log(group.toStringDetailed());
28 +
29 + // Delete the new Group
30 + return api.groups.deleteGroup(group);
31 + });
32 + })
33 + .catch(err => {
34 + console.error(err);
35 + })
36 +;
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +const model = v3.model;
8 +
9 +// Replace this with your Bridge User name
10 +const USERNAME = require('../../../test/support/testValues').username;
11 +
12 +
13 +v3.discovery.nupnpSearch()
14 + .then(searchResults => {
15 + const host = searchResults[0].ipaddress;
16 + return v3.api.createLocal(host).connect(USERNAME);
17 + })
18 + .then(api => {
19 + const newRoom = model.createRoom();
20 + // The name of the new room we are creating
21 + newRoom.name = 'Testing Room Creation';
22 + // The class of the room we are creating, these are specified in the Group documentation under class attribute
23 + newRoom.class = 'Gym';
24 +
25 + return api.groups.createGroup(newRoom)
26 + .then(room => {
27 + console.log(room.toStringDetailed());
28 +
29 + // Delete the new Room
30 + return api.groups.deleteGroup(room);
31 + });
32 + })
33 + .catch(err => {
34 + console.error(err);
35 + })
36 +;
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +const model = v3.model;
8 +
9 +// Replace this with your Bridge User name
10 +const USERNAME = require('../../../test/support/testValues').username;
11 +
12 +
13 +v3.discovery.nupnpSearch()
14 + .then(searchResults => {
15 + const host = searchResults[0].ipaddress;
16 + return v3.api.createLocal(host).connect(USERNAME);
17 + })
18 + .then(api => {
19 + const newZone = model.createZone();
20 + // The name of the new zone we are creating
21 + newZone.name = 'Testing Zone Creation';
22 + // The array of light ids that will be in the zone
23 + newZone.lights = [2, 3, 4, 5];
24 + // The class for the zone, this has to be selected from the valid value, consult the documentation for details
25 + newZone.class = 'Toilet';
26 +
27 + return api.groups.createGroup(newZone)
28 + .then(zone => {
29 + console.log(zone.toStringDetailed());
30 +
31 + // Delete the new Zone
32 + return api.groups.deleteGroup(zone);
33 + });
34 + })
35 + .catch(err => {
36 + console.error(err);
37 + })
38 +;
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +const USERNAME = require('../../../test/support/testValues').username;
8 +
9 +
10 +v3.discovery.nupnpSearch()
11 + .then(searchResults => {
12 + const host = searchResults[0].ipaddress;
13 + return v3.api.createLocal(host).connect(USERNAME);
14 + })
15 + .then(api => {
16 + // Create a new group that we can then delete
17 + const zone = v3.model.createZone();
18 + zone.name = 'Testing Group Deletion';
19 +
20 + return api.groups.createGroup(zone)
21 + .then(group => {
22 + // Display the new group
23 + console.log(group.toStringDetailed());
24 +
25 + // Delete the group we just created
26 + return api.groups.deleteGroup(group.id);
27 + });
28 + })
29 + .then(result => {
30 + console.log(`Deleted group? ${result}`);
31 + })
32 + .catch(err => {
33 + console.error(err);
34 + })
35 +;
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +const USERNAME = require('../../../test/support/testValues').username;
8 +
9 +v3.discovery.nupnpSearch()
10 + .then(searchResults => {
11 + const host = searchResults[0].ipaddress;
12 + return v3.api.createLocal(host).connect(USERNAME);
13 + })
14 + .then(api => {
15 + return api.groups.getAll();
16 + })
17 + .then(getAllGroups => {
18 + // Iterate over the light objects showing details
19 + getAllGroups.forEach(group => {
20 + console.log(group.toStringDetailed());
21 + });
22 + })
23 +;
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +const USERNAME = require('../../../test/support/testValues').username;
8 +
9 +// THe id of the group to retrieve
10 +const GROUP_ID = 1;
11 +
12 +
13 +v3.discovery.nupnpSearch()
14 + .then(searchResults => {
15 + const host = searchResults[0].ipaddress;
16 + return v3.api.createLocal(host).connect(USERNAME);
17 + })
18 + .then(api => {
19 + return api.groups.getGroup(GROUP_ID);
20 + })
21 + .then(group => {
22 + // Display the details for the group
23 + console.log(group.toStringDetailed());
24 + })
25 +;
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +const USERNAME = require('../../../test/support/testValues').username;
8 +
9 +// The nameof the group(s) to retrieve
10 +const GROUP_NAME = 'VRC 1';
11 +
12 +
13 +v3.discovery.nupnpSearch()
14 + .then(searchResults => {
15 + const host = searchResults[0].ipaddress;
16 + return v3.api.createLocal(host).connect(USERNAME);
17 + })
18 + .then(api => {
19 + return api.groups.getGroupByName(GROUP_NAME);
20 + })
21 + .then(matchedGroups => {
22 + if (matchedGroups && matchedGroups.length > 0) {
23 + // Iterate over the light objects showing details
24 + matchedGroups.forEach(group => {
25 + console.log(group.toStringDetailed());
26 + });
27 + } else {
28 + console.log(`No groups found with names that match: '${GROUP_NAME}'`);
29 + }
30 + })
31 +;
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +const USERNAME = require('../../../test/support/testValues').username;
8 +
9 +
10 +v3.discovery.nupnpSearch()
11 + .then(searchResults => {
12 + const host = searchResults[0].ipaddress;
13 + return v3.api.createLocal(host).connect(USERNAME);
14 + })
15 + .then(api => {
16 +
17 + const promises = [];
18 +
19 + // Get and display Light Groups
20 + promises.push(
21 + api.groups.getLightGroups()
22 + .then(displayGroups('LightGroups'))
23 + );
24 +
25 + // Get and display Luminaires
26 + promises.push(
27 + api.groups.getLuminaries()
28 + .then(displayGroups('Luminaries'))
29 + );
30 +
31 + // Get and display LightSources
32 + promises.push(
33 + api.groups.getLightSources()
34 + .then(displayGroups('LightSources'))
35 + );
36 +
37 + // Get and display Rooms
38 + promises.push(
39 + api.groups.getRooms()
40 + .then(displayGroups('Rooms'))
41 + );
42 +
43 + // Get and display Zones
44 + promises.push(
45 + api.groups.getZones()
46 + .then(displayGroups('Zones'))
47 + );
48 +
49 + // Get and display Entertainment
50 + promises.push(
51 + api.groups.getEntertainment()
52 + .then(displayGroups('Entertainment'))
53 + );
54 +
55 + return Promise.all(promises);
56 + })
57 +;
58 +
59 +
60 +function displayGroups(type) {
61 + return function (groups) {
62 + console.log('*************************************************************');
63 + console.log(`Group Type: ${type}`);
64 + if (groups && groups.length > 0) {
65 + groups.forEach(group => {
66 + console.log(group.toStringDetailed());
67 + });
68 + } else {
69 + console.log('No matching groups in Hue Bridge');
70 + }
71 + console.log('*************************************************************');
72 + };
73 +}
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3
4 + , GroupLightState = v3.lightStates.GroupLightState
5 +;
6 +// If using this code outside of this library the above should be replaced with
7 +// const v3 = require('node-hue-api').v3;
8 +
9 +const USERNAME = require('../../../test/support/testValues').username;
10 +
11 +// The target Group id that we will set the light state on. Using the all groups group here as that will always be present.
12 +const GROUP_ID = 0;
13 +
14 +
15 +v3.discovery.nupnpSearch()
16 + .then(searchResults => {
17 + const host = searchResults[0].ipaddress;
18 + return v3.api.createLocal(host).connect(USERNAME);
19 + })
20 + .then(api => {
21 + // Build a desired light state for the group
22 + const groupState = new GroupLightState()
23 + .on()
24 + .brightness(20)
25 + .saturation(50)
26 + ;
27 +
28 + return api.groups.setGroupState(GROUP_ID, groupState);
29 + })
30 + .then(result => {
31 + console.log(`Successfully set group light state? ${result}`);
32 + })
33 + .catch(err => {
34 + console.error(err);
35 + })
36 +;
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3
4 + , model = v3.model;
5 +// If using this code outside of this library the above should be replaced with
6 +// const v3 = require('node-hue-api').v3
7 +// , model = v3.model;
8 +
9 +const USERNAME = require('../../../test/support/testValues').username;
10 +
11 +// Flag indicating whether or not to clean up, i.e. delete the group we getOperator as part of this example
12 +const CLEANUP = true;
13 +
14 +// The Id of the group that we will getOperator
15 +let createdGroupId = null;
16 +
17 +
18 +v3.discovery.nupnpSearch()
19 + .then(searchResults => {
20 + const host = searchResults[0].ipaddress;
21 + return v3.api.createLocal(host).connect(USERNAME);
22 + })
23 + .then(api => {
24 + // Create a new group that we can modify the attributes on
25 + const zone = model.createZone();
26 + zone.name = 'Testing Group Update Attributes';
27 +
28 + return api.groups.createGroup(zone)
29 + .then(group => {
30 + // Display the new group
31 + console.log(group.toStringDetailed());
32 +
33 + // Store the ID so we can later remove it
34 + createdGroupId = group.id;
35 +
36 + // Update the name of the group
37 + group.name = 'A new group name';
38 + // Update the name on the group (can also do 'class' for the room class and 'lights' to update the lights associated with the group)
39 + return api.groups.updateGroupAttributes(group);
40 + })
41 + .then(result => {
42 + // Display the result of the
43 + console.log(`Update group attributes? ${result}`);
44 + })
45 + .then(() => {
46 + if (CLEANUP && createdGroupId) {
47 + console.log('Cleaning up and removing group that was created');
48 + return api.groups.deleteGroup(createdGroupId);
49 + }
50 + });
51 + })
52 + .catch(err => {
53 + console.error(err);
54 + })
55 +;
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +// Replace this with your username for accessing the bridge
8 +const USERNAME = require('../../../test/support/testValues').username
9 + // The name of the light we wish to retrieve by name
10 + , LIGHT_ID = 1000
11 +;
12 +
13 +v3.discovery.nupnpSearch()
14 + .then(searchResults => {
15 + const host = searchResults[0].ipaddress;
16 + return v3.api.createLocal(host).connect(USERNAME);
17 + })
18 + .then(api => {
19 + return api.lights.deleteLight(LIGHT_ID);
20 + })
21 + .then(result => {
22 + // Display the state of the light
23 + console.log(`Successfully delete light? ${result}`);
24 + })
25 +;
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +const USERNAME = require('../../../test/support/testValues').username;
8 +
9 +v3.discovery.nupnpSearch()
10 + .then(searchResults => {
11 + const host = searchResults[0].ipaddress;
12 + return v3.api.createLocal(host).connect(USERNAME);
13 + })
14 + .then(api => {
15 + return api.lights.getAll();
16 + })
17 + .then(allLights => {
18 + // Display the details of the lights we got back
19 + console.log(JSON.stringify(allLights, null, 2));
20 +
21 + // Iterate over the light objects showing details
22 + allLights.forEach(light => {
23 + console.log(light.toStringDetailed());
24 + });
25 + })
26 + .catch(err => {
27 + console.error(err);
28 + })
29 +;
...\ No newline at end of file ...\ No newline at end of file
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +// Replace this with your username for accessing the bridge
8 +const USERNAME = require('../../../test/support/testValues').username
9 + // The name of the light we wish to retrieve by id
10 + , LIGHT_ID = 10
11 +;
12 +
13 +v3.discovery.nupnpSearch()
14 + .then(searchResults => {
15 + const host = searchResults[0].ipaddress;
16 + return v3.api.createLocal(host).connect(USERNAME);
17 + })
18 + .then(api => {
19 + return api.lights.getLight(LIGHT_ID);
20 + })
21 + .then(light => {
22 + // Display the details of the light
23 + console.log(light.toStringDetailed());
24 + })
25 +;
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +// Replace this with your username for accessing the bridge
8 +const USERNAME = require('../../../test/support/testValues').username
9 + // The name of the light we wish to retrieve by name
10 + , LIGHT_ID = 10
11 +;
12 +
13 +v3.discovery.nupnpSearch()
14 + .then(searchResults => {
15 + const host = searchResults[0].ipaddress;
16 + return v3.api.createLocal(host).connect(USERNAME);
17 + })
18 + .then(api => {
19 + return api.lights.getLightAttributesAndState(LIGHT_ID);
20 + })
21 + .then(attributesAndState => {
22 + // Display the details of the light
23 + console.log(JSON.stringify(attributesAndState, null, 2));
24 + })
25 +;
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +// Replace this with your username for accessing the bridge
8 +const USERNAME = require('../../../test/support/testValues').username
9 + // The name of the light we wish to retrieve by name
10 + , LIGHT_NAME = 'Bench corner'
11 +;
12 +
13 +v3.discovery.nupnpSearch()
14 + .then(searchResults => {
15 + const host = searchResults[0].ipaddress;
16 + return v3.api.createLocal(host).connect(USERNAME);
17 + })
18 + .then(api => {
19 + return api.lights.getLightByName(LIGHT_NAME);
20 + })
21 + .then(light => {
22 + if (light) {
23 + // Display the details of the light
24 + console.log(light.toStringDetailed());
25 + } else {
26 + console.log(`Failed to find a light with name '${LIGHT_NAME}'`);
27 + }
28 + })
29 +;
1 +'use strict';
2 +
3 +const v3 = require('../../../index').v3;
4 +// If using this code outside of this library the above should be replaced with
5 +// const v3 = require('node-hue-api').v3;
6 +
7 +// Replace this with your username for accessing the bridge
8 +const USERNAME = require('../../../test/support/testValues').username
9 + // The name of the light we wish to retrieve by name
10 + , LIGHT_ID = 10
11 +;
12 +
13 +v3.discovery.nupnpSearch()
14 + .then(searchResults => {
15 + const host = searchResults[0].ipaddress;
16 + return v3.api.createLocal(host).connect(USERNAME);
17 + })
18 + .then(api => {
19 + return api.lights.getLightState(LIGHT_ID);
20 + })
21 + .then(state => {
22 + // Display the state of the light
23 + console.log(JSON.stringify(state, null, 2));
24 + })
25 +;
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.