{"id":13527883,"url":"https://github.com/sqmk/huejay","last_synced_at":"2026-02-03T18:44:35.710Z","repository":{"id":1621888,"uuid":"43342549","full_name":"sqmk/huejay","owner":"sqmk","description":"Philips Hue client for Node.js","archived":false,"fork":false,"pushed_at":"2022-02-25T11:22:11.000Z","size":455,"stargazers_count":424,"open_issues_count":19,"forks_count":40,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-10-01T00:58:23.432Z","etag":null,"topics":["client","hue","javascript","nodejs","philips"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sqmk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-09-29T03:27:02.000Z","updated_at":"2025-09-10T18:34:30.000Z","dependencies_parsed_at":"2022-08-06T11:00:13.334Z","dependency_job_id":null,"html_url":"https://github.com/sqmk/huejay","commit_stats":null,"previous_names":[],"tags_count":71,"template":false,"template_full_name":null,"purl":"pkg:github/sqmk/huejay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqmk%2Fhuejay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqmk%2Fhuejay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqmk%2Fhuejay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqmk%2Fhuejay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sqmk","download_url":"https://codeload.github.com/sqmk/huejay/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sqmk%2Fhuejay/sbom","scorecard":{"id":843060,"data":{"date":"2025-08-11","repo":{"name":"github.com/sqmk/huejay","commit":"92be1ebb960ca7fb0001544dc8e7f1c47213cb5c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":1,"reason":"Found 3/21 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 13 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-23T20:53:08.597Z","repository_id":1621888,"created_at":"2025-08-23T20:53:08.597Z","updated_at":"2025-08-23T20:53:08.597Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29053304,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T15:43:47.601Z","status":"ssl_error","status_checked_at":"2026-02-03T15:43:46.709Z","response_time":96,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["client","hue","javascript","nodejs","philips"],"created_at":"2024-08-01T06:02:05.083Z","updated_at":"2026-02-03T18:44:35.684Z","avatar_url":"https://github.com/sqmk.png","language":"JavaScript","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://cdn.rawgit.com/sqmk/huejay/db9081ee1a22acf77abc93cbd3f2e8f6d20ee16b/media/huejay.svg\" alt=\"Huejay\" /\u003e\n\u003c/p\u003e\n\n# Huejay - Philips Hue client for Node.js\n\n[![NPM Version](https://img.shields.io/npm/v/huejay.svg)](https://www.npmjs.com/package/huejay)\n[![Build Status](https://img.shields.io/travis/sqmk/huejay/master.svg)](https://travis-ci.org/sqmk/huejay)\n[![Dependency Status](https://img.shields.io/david/sqmk/huejay.svg)](https://david-dm.org/sqmk/huejay)\n[![Greenkeeper badge](https://badges.greenkeeper.io/sqmk/huejay.svg)](https://greenkeeper.io/)\n\nHuejay is the most in-depth Node.js client for the Philips Hue home lighting system.\n\nUse Huejay to interact with Philips Hue in the following ways:\n- [Discover bridges](#bridge-discovery)\n- [Manage bridge settings](#bridge)\n- [Manage portal settings](#portal)\n- [Manage software updates](#software-update)\n- [Manage users](#users)\n- [Manage lights](#lights)\n- [Manage groups](#groups)\n- [Manage schedules](#schedules)\n- [Manage scenes](#scenes)\n- [Manage sensors](#sensors)\n- [Manage rules](#rules)\n- [Manage resource links](#resource-links)\n- [Retrieve capabilities](#capabilities)\n- [Retrieve internet services](#internet-services)\n\nPhilips Hue API version supported: **1.19.0**\n\n## Documentation\n\n- [Installation](#installation)\n- [Basic Usage](#basic-usage)\n- [Bridge Discovery](#bridge-discovery)\n- [Errors](#errors)\n- [Client Usage](#client-usage)\n  - [Users](#users)\n  - [Bridge](#bridge)\n  - [Portal](#portal)\n  - [Software Update](#software-update)\n  - [Internet Services](#internet-services)\n  - [Lights](#lights)\n  - [Groups](#groups)\n  - [Schedules](#schedules)\n    - [Time Patterns](#time-patterns)\n    - [Actions](#actions)\n  - [Scenes](#scenes)\n  - [Sensors](#sensors)\n  - [Rules](#rules)\n  - [Resource Links](#resource-links)\n  - [Capabilities](#capabilities)\n  - [Time Zones](#time-zones)\n\n## Installation\n\nHuejay was written for **Node.js 4+**.\n\n`npm install --save huejay`\n\n## Basic Usage\n\nRequiring the library is simple:\n\n```js\nlet huejay = require('huejay');\n```\n\nMost methods return a `Promise` as a result. These are native Node.js promises.\n\n## Bridge Discovery\n\nBefore interacting with your Hue system, you may want to know the availability\nand IP addresses of your bridges. You can use Huejay's `discover` method to find\nthem.\n\n```js\nhuejay.discover()\n  .then(bridges =\u003e {\n    for (let bridge of bridges) {\n      console.log(`Id: ${bridge.id}, IP: ${bridge.ip}`);\n    }\n  })\n  .catch(error =\u003e {\n    console.log(`An error occurred: ${error.message}`);\n  });\n```\n\nHuejay offers several strategies for bridge discovery:\n* **nupnp**: Default option, uses Meethue's public API to discover local bridges\n* **upnp**: Uses SSDP to discover local bridges\n* **all**: Uses all available strategies for discovery\n\nTo use a specific discovery strategy:\n\n```js\nhuejay.discover({strategy: 'upnp'})\n  .then(bridges =\u003e {\n    console.log(bridges);\n  });\n```\n\n## Errors\n\nNearly all errors returned by Huejay are of type `huejay.Error`. Use this to\ncheck Huejay specific errors.\n\nErrors originating from the bridge return an additional `type` property.\nThis value is the error number as returned by the Philips Hue API.\n\n## Client Usage\n\nYou can use Huejay to retrieve and manipulate resources on your preferred bridge.\nResources include users, lights, groups, scenes, and others.\n\nTo start, you must instantiate a client. The `Client` class is available for\nconvenience via Huejay;\n\n```js\nlet client = new huejay.Client({\n  host:     '123.0.12.34',\n  port:     80,               // Optional\n  username: 'bridgeusername', // Optional\n  timeout:  15000,            // Optional, timeout in milliseconds (15000 is the default)\n});\n```\n\nIf a *username* is not provided, nearly all commands will fail due to failure to\nauthenticate with the bridge. Be sure to provide a valid *username* to use all\nclient commands.\n\nThe *timeout* option applies to bridge commands. The default value is 15000\nmilliseconds (or 15 seconds).\n\n### Users\n\nHuejay provides several commands for managing users on Philips Hue bridges.\n\n#### client.users.create - Create user\n\nYou can use Huejay to create users on the bridge. Creating a user requires the\nbridge's link button to be pressed. The link button is activated for roughly\n30 seconds.\n\nTo create a user, instantiate a `User` object and pass it to `client.users.create`.\nOn successful creation, a brand new `User` object is returned by way of a `Promise`.\nThe `User` object will contain a username generated by the bridge. You can use\nthis username to authenticate against the bridge going forward.\n\n```js\nlet user = new client.users.User;\n\n// Optionally configure a device type / agent on the user\nuser.deviceType = 'my_device_type'; // Default is 'huejay'\n\nclient.users.create(user)\n  .then(user =\u003e {\n    console.log(`New user created - Username: ${user.username}`);\n  })\n  .catch(error =\u003e {\n    if (error instanceof huejay.Error \u0026\u0026 error.type === 101) {\n      return console.log(`Link button not pressed. Try again...`);\n    }\n\n    console.log(error.stack);\n  });\n```\n\n*Note: The bridge does not permit supplying your own username.*\n\n*Note: It is possible to use Huejay to toggle the link button if you are already\nauthenticated with the bridge. This may save you from walking over to the bridge\nto physically press the link button. See `client.bridge.save` and `Bridge`\n`linkButtonEnabled`.*\n\n#### client.users.get - Get authenticated user\n\nIf the username assigned to the client is legitimate, you can get the details for\nthis user by calling `client.users.get`.\n\n```js\nclient.users.get()\n  .then(user =\u003e {\n    console.log('Username:', user.username);\n    console.log('Device type:', user.deviceType);\n    console.log('Create date:', user.created);\n    console.log('Last use date:', user.lastUsed);\n  });\n```\n\n#### client.users.getByUsername - Get user by username\n\nAlthough the bridge does not provide an equivalent API for retrieving a user\nby username, Huejay provides a means to do so.\n\nSimply pass in a string containing username to `client.users.getByUsername` to\nlook up the user.\n\n```js\nclient.users.getByUsername('usernamehere')\n  .then(user =\u003e {\n    console.log(`Username: ${user.username}`);\n  });\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\nIf a user is not found with the provided username, a `huejay.Error` is thrown.\n\n#### client.users.getAll - Get all users\n\nWant to retrieve all users assigned to the bridge? You can use\n`client.users.getAll` to do so. This method will return an array of `User`\nobjects.\n\n```js\nclient.users.getAll()\n  .then(users =\u003e {\n    for (let user of users) {\n      console.log(`Username: ${user.username}`);\n    }\n  });\n```\n\n#### client.users.delete - Delete a user\n\nDeleting users using Huejay is simple. Provide either a username or `User`\nobject to `client.users.delete` to delete a user.\n\n```js\nclient.users.delete('usernamehere')\n  .then(() =\u003e {\n    console.log('User was deleted');\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\n### Bridge\n\nHuejay supports retrieving and configuring the Philips Hue bridge. It supports\ntesting connection and authentication to the bridge as well.\n\n#### client.bridge.ping - Test connection to the bridge\n\nUse `client.bridge.ping` to test connection to your preferred bridge. Failed\nconnection results in a thrown `huejay.Error`.\n\n```js\nclient.bridge.ping()\n  .then(() =\u003e {\n    console.log('Successful connection');\n  })\n  .catch(error =\u003e {\n    console.log('Could not connect');\n  });\n```\n\n#### client.bridge.isAuthenticated - Test authentication to the bridge\n\nTo ensure your supplied client username can authenticate to the bridge, use\n`client.bridge.isAuthenticated`. Authentication or connection failure will\nresult `huejay.Error` being thrown.\n\n```js\nclient.bridge.isAuthenticated()\n  .then(() =\u003e {\n    console.log('Successful authentication');\n  })\n  .catch(error =\u003e {\n    console.log('Could not authenticate');\n  });\n```\n\n#### client.bridge.get - Get bridge details and configuration\n\nWant to get bridge details? Use Huejay's `client.bridge.get`\nmethod. This will return a `Bridge` object, which can be used for reading\nand saving configuration.\n\n```js\nclient.bridge.get()\n  .then(bridge =\u003e {\n    console.log(`Retrieved bridge ${bridge.name}`);\n    console.log('  Id:', bridge.id);\n    console.log('  Model Id:', bridge.modelId);\n    console.log('  Model Name:', bridge.model.name);\n  });\n```\n\nAttributes available on the `Bridge` object:\n- `id` - Unique\n- `name` - Name of the bridge\n- `modelId` - Model Id\n- `model` - A `BridgeModel` object, containing details about the model\n- `factoryNew` - Whether or not the bridge is factory new\n- `replacesBridgeId` - Replaces bridge id (for migrating from old bridges)\n- `dataStoreVersion` - Data store version\n- `starterKitId` - Name of the starterkit created in the factory\n- `softwareVersion` - Software version of the bridge\n- `apiVersion` - API version of the bridge\n- `zigbeeChannel` - ZigBee channel (for communicating with lights)\n- `macAddress` - MAC address\n- `ipAddress` - IP address\n- `dhcpEnabled` - Whether or not DHCP is enabled\n- `netmask` - Netmask\n- `gateway` - Gateway\n- `proxyAddress` - Proxy address\n- `proxyPort` - Proxy port\n- `utcTime` - UTC time of the bridge\n- `timeZone` - Time zone\n- `localTime` - Local time of the bridge\n- `portalServicesEnabled` - Whether or not portal services are enabled\n- `portalConnected` - Whether or not portal is connected\n- `linkButtonEnabled` - Whether or not link button is enabled\n- `touchlinkEnabled` - Whether or not Touchlink is enabled\n\nThe `Bridge` `model` attribute returns a `BridgeModel` object which contains\nadditional details about the model:\n- `id` - Model Id, typically the same value as `Bridge` `modelId`\n- `manufacturer` - Manufacturer (e.g. Philips)\n- `name` - Name of the model / product (e.g. Hue v1, Hue v2)\n\n#### client.bridge.save - Save bridge configuration\n\nYou can configure the bridge by changing values on the `Bridge` object and\npassing to the `client.bridge.save` method. This method will return the same\n`Bridge` for further manipulation.\n\n```js\nclient.bridge.get()\n  .then(bridge =\u003e {\n    // Change bridge's name\n    bridge.name = 'New bridge name';\n\n    return client.bridge.save(bridge);\n  })\n  .then(bridge =\u003e {\n    console.log(`Bridge is now named ${bridge.name}`);\n  });\n```\n\nThe following `Bridge` attributes are configurable:\n- `name` - Name of the bridge\n- `zigbeeChannel` - Preferred ZigBee channel\n- `ipAddress` - IP address\n- `dhcpEnabled` - `true` to enable, `false` to disable\n- `netmask` - Netmask\n- `gateway` - Gateway\n- `proxyPort` - Proxy port\n- `proxyAddress` - Proxy address\n- `timeZone` - Any value available in `client.timeZones.getAll`\n- `linkButtonEnabled` - `true` to toggle on temporarily\n- `touchlinkEnabled` - `true` to toggle on temporarily\n\n#### client.bridge.linkButton - Simulate link button press\n\nUse this command with an authenticated user to simulate pressing the link\nbutton. No need to physically press the button on your bridge for creating users\nand other actions.\n\n```js\nclient.bridge.linkButton()\n  .then(() =\u003e {\n    console.log('Link button was pressed');\n  });\n```\n\n#### client.bridge.touchlink - Enable Touchlink\n\nHaving issues pairing new lights to your bridge? Reset your bridge and can't\nseem to find your existing lights? Use Huejay to enable Touchlink and steal\nthose lights back. This is commonly known in the community as \"Lamp stealer\".\n\nTouchlink is enabled for roughly 30 seconds.\n\n```js\nclient.bridge.touchlink()\n  .then(() =\u003e {\n    console.log('Touchlink is enabled');\n  });\n```\n\nYou can set `touchlinkEnabled` on the `Bridge` object and save to achieve\nthe same effect as this command.\n\n### Portal\n\nThe Philips Hue bridge allows connection to Philips' Meethue.com portal\nservices. You can use Meethue.com to remotely configure numerous resources\non your bridge, including lights, devices, and scenes.\n\nHuejay provides a way to retrieve Meethue's portal connectivity details.\n\n#### client.portal.get - Get portal details\n\nUse `client.portal.get` to retrieve connectivity details. This method will\nreturn a `Portal` object.\n\n```js\nclient.portal.get()\n  .then(portal =\u003e {\n    console.log('Is signed on:', portal.signedOn);\n    console.log('Incoming:', portal.incoming);\n    console.log('Outgoing:', portal.outgoing);\n    console.log('Communication:', portal.communication);\n  });\n```\n\n### Software Update\n\nOccasionally, Philips releases new updates for the bridge, lights, and devices.\nYou can use Huejay to facilitate downloading and installation of updates.  \n\n#### client.softwareUpdate.get - Get software update details\n\nTo get software update details, use the `client.softwareUpdate.get` method to\nretrieve a `SoftwareUpdate` object. This object provides details about any\npending updates to the bridge or other resources.\n\n```js\nclient.softwareUpdate.get()\n  .then(softwareUpdate =\u003e {\n    console.log('State:', softwareUpdate.state);\n    console.log('Release URL:', softwareUpdate.releaseUrl);\n    console.log('Release notes:', softwareUpdate.releaseNotes);\n  });\n```\n\nThe following attributes are available on the `SoftwareUpdate` object:\n- `state` - Update state, see below for values\n- `checkingEnabled` - `true` if bridge is checking for updates, `false` if not\n- `bridge` - `true` if updates are available for the bridge, `false` if not\n- `lights` - An array of light ids with available updates\n- `sensors` - An array of sensor ids with available updates\n- `releaseUrl` - Release URL\n- `releaseNotes` - Release notes\n- `installNotificationEnabled` - Whether or not the install notification is enabled\n\nThe following are possible `state` values:\n- `NO_UPDATE` - There are no updates available\n- `DOWNLOADING` - Updates are being downloaded\n- `READY_TO_INSTALL` - Updates are ready to be installed\n- `INSTALLING` - Updates are installing\n\n#### client.softwareUpdate.check - Make bridge check for software updates\n\nYou can request the bridge to check for software updates. Call the\n`client.softwareUpdate.check` method to have the bridge start checking for\nupdates. A `huejay.Error` is thrown if the bridge is already checking.\n\n```js\nclient.softwareUpdate.check()\n  .then(() =\u003e {\n    console.log('Bridge is checking for software updates');\n  });\n```\n\n#### client.softwareUpdate.install - Start installation of pending updates\n\nIf there are any pending software updates, you can use `client.softwareUpdate.install`\nto install them. A `huejay.Error` is thrown if there are no updates to install.\n\n```js\nclient.softwareUpdate.install()\n  .then(() =\u003e {\n    console.log('Installation has begun');\n  });\n```\n\n#### client.softwareUpdate.disableInstallNotification - Disables install notification\n\nTo disable the install notification (useful for mobile apps),\n`client.softwareUpdate.disableInstallNotification` will allow you to turn off the\nnotification. This only works when the notification is enabled.\n\n```js\nclient.softwareUpdate.disableInstallNotification()\n  .then(() =\u003e {\n    console.log('Install notification is now disabled');\n  });\n```\n\n### Internet Services\n\nInterested in finding out what internet services are connected and functioning on your bridge?\n\n#### client.internetServices.get - Get internet services details\n\nUse this command for retrieving information about what internet services are connected.\n\n```js\nclient.internetServices.get()\n  .then(internetServices =\u003e {\n    console.log(`Internet: ${internetServices.internetConnected}`);\n    console.log(`Remote access: ${internetServices.remoteAccessConnected}`);\n    console.log(`Time sync: ${internetServices.timeSyncConnected}`);\n    console.log(`Software update: ${internetServices.softwareUpdateConnected}`);\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n\n```\n\n### Lights\n\nThe Philips Hue API exposes numerous endpoints for managing your lights. Huejay\nsupports it all, from searching and installing new lights, to changing light\nattributes and state.\n\n#### client.lights.scan - Scan for new lights\n\nHooked up a fresh Philips Hue bridge? Plugged in brand new bulbs or a fixture?\nBefore you can interact with your new lights, you'll need to add them to your\npreferred bridge.\n\nHuejay's `client.lights.scan` will get your bridge to start scanning for new,\nunregistered lights. Scans last roughly 30 seconds. New bulbs can then be\nretrieved by using `client.lights.getNew`.\n\n```js\nclient.lights.scan()\n  .then(() =\u003e {\n    console.log('Started new light scan');\n  });\n```\n\n*Note: Make sure your bulbs are powered on for your bridge to find them.*\n\n#### client.lights.getNew - Get new lights\n\nWhen bulbs are freshly registered on the bridge, you can retrieve them using\n`client.lights.getNew`. This command will ultimately return an array of `Light` objects.\n\n```js\nclient.lights.getNew()\n  .then(lights =\u003e {\n    console.log('Found new lights:');\n    for (let light of lights) {\n      console.log(`Light [${light.id}]:`);\n      console.log('  Unique Id:', light.uniqueId);\n      console.log('  Model:',     light.model.name);\n      console.log('  Reachable:', light.reachable);\n    }\n  });\n```\n\nMore information on `Light` objects is available in the following commands below.\n\n#### client.lights.getAll - Get all registered lights\n\nHuejay's `client.lights.getAll` will return a list of all registered lights on\nthe bridge. Like `client.lights.getNew`, the result from the completed `Promise`\nwill be an array of `Light` objects.\n\n```js\nclient.lights.getAll()\n  .then(lights =\u003e {\n    for (let light of lights) {\n      console.log(`Light [${light.id}]: ${light.name}`);\n      console.log(`  Type:             ${light.type}`);\n      console.log(`  Unique ID:        ${light.uniqueId}`);\n      console.log(`  Manufacturer:     ${light.manufacturer}`);\n      console.log(`  Model Id:         ${light.modelId}`);\n      console.log('  Model:');\n      console.log(`    Id:             ${light.model.id}`);\n      console.log(`    Manufacturer:   ${light.model.manufacturer}`);\n      console.log(`    Name:           ${light.model.name}`);\n      console.log(`    Type:           ${light.model.type}`);\n      console.log(`    Color Gamut:    ${light.model.colorGamut}`);\n      console.log(`    Friends of Hue: ${light.model.friendsOfHue}`);\n      console.log(`  Software Version: ${light.softwareVersion}`);\n      console.log('  State:');\n      console.log(`    On:         ${light.on}`);\n      console.log(`    Reachable:  ${light.reachable}`);\n      console.log(`    Brightness: ${light.brightness}`);\n      console.log(`    Color mode: ${light.colorMode}`);\n      console.log(`    Hue:        ${light.hue}`);\n      console.log(`    Saturation: ${light.saturation}`);\n      console.log(`    X/Y:        ${light.xy[0]}, ${light.xy[1]}`);\n      console.log(`    Color Temp: ${light.colorTemp}`);\n      console.log(`    Alert:      ${light.alert}`);\n      console.log(`    Effect:     ${light.effect}`);\n      console.log();\n    }\n  });\n```\n\nThe following `Light` attributes are available:\n- `id` - Numerical id of the light as registered on the bridge\n- `name` - Configurable name for the light\n- `type` - Type of light (e.g. Extended Color Light, Dimmable Light)\n- `uniqueId` - Unique Id of the light\n- `manufacturer` - Name of the manufacturer\n- `modelId` - Model Id of the light, used for determining `LightModel`\n- `model` - A `LightModel` object, containing details about the model (not available in other Node.js clients!)\n- `productId` - Unique identifying hardware model (*Note: Not available for all lights*)\n- `softwareVersion` - Software version of the light\n- `softwareConfigId` - Software config id of the light (*Note: Not available for all lights*)\n\nThe following `Light` state is available:\n- `on` - `true` if the light is on, `false` if not, configurable\n- `reachable` - `true` if the light can be communicated with, `false` if not\n- `brightness` - Configurable brightness of the light (value from 0 to 254)\n- `colorMode` - Color mode light is respecting (e.g. ct, xy, hs)\n- `hue` - Configurable hue of the light (value from 0 to 65535)\n- `saturation` - Configurable saturation of the light, compliments `hue` (value from 0 to 254)\n- `xy` - Configurable CIE x and y coordinates (value is an array containing x and y values)\n- `colorTemp` - Configurable Mired Color temperature of the light (value from 153 to 500)\n- `transitionTime` - Configurable temporary value which eases transition of an effect (value in seconds, 0 for instant, 5 for five seconds)\n- `alert` - Configurable alert effect (e.g. none, select, lselect)\n- `effect` - Configurable effect (e.g. none, colorloop)\n\nThere are additional `Light` state properties available for incrementing and\ndecrementing values:\n- `incrementBrightness` - Increment or decrement brightness value\n- `incrementHue` - Increment or decrement hue value\n- `incrementSaturation` - Increment or decrement saturation value\n- `incrementXy` - Increment or decrement xy values\n- `incrementColorTemp` - Increment or decrement color temperature value\n\nHuejay is the only Node.js client that maintains a list of Philips Hue supported\nmodels. The `Light` `model` attribute returns a `LightModel` object which contains\nadditional details about the model:\n- `id` - Model Id, typically the same value as `Light` `modelId`\n- `manufacturer` - Manufacturer, typically the same value as `Light` `manufacturer`\n- `name` - Name of the model / product (e.g. Hue Spot GU10)\n- `type` - Type of light, typically the same value as `Light` `type`\n- `colorGamut` - The supported color gamut of the light\n- `friendsOfHue` - `true` if Friends of Hue, `false` if not\n\n#### client.lights.getById - Get light by id\n\nIf only a single light is needed, `client.lights.getById` can be used to fetch\na light by its bridge assigned id. A `Light` object is returned if the light is\nfound, else a `huejay.Error` is thrown.\n\n```js\nclient.lights.getById(1)\n  .then(light =\u003e {\n    console.log('Found light:');\n    console.log(`  Light [${light.id}]: ${light.name}`);\n  })\n  .catch(error =\u003e {\n    console.log('Could not find light');\n    console.log(error.stack);\n  });\n```\n\n#### client.lights.save - Save a light's attributes and state\n\nAfter retrieving a `Light` object through previous commands, you can configure\nthe light and save its attributes and state. This allows you to change a\nlight's name, color, effect, and so on. You can set various properties on a\n`Light` object, and save them via `client.lights.save`.\n\nHuejay is smart and keeps track of changed attributes and state. The client\nwill only send updated values to the Philips Hue bridge, as sending all\nconfigurable attributes and state can affect bridge and light performance.\n\nTo save a light, pass a `Light` object to `client.lights.save`. The light is\nreturned after saving for convenient chaining.\n\n```js\nclient.lights.getById(3)\n  .then(light =\u003e {\n    light.name = 'New light name';\n\n    light.brightness = 254;\n    light.hue        = 32554;\n    light.saturation = 254;\n\n    return client.lights.save(light);\n  })\n  .then(light =\u003e {\n    console.log(`Updated light [${light.id}]`);\n  })\n  .catch(error =\u003e {\n    console.log('Something went wrong');\n    console.log(error.stack);\n  });\n```\n\nThe following `Light` object attributes and state are configurable:\n- `name`\n- `on`\n- `brightness`\n- `hue`\n- `saturation`\n- `xy`\n- `colorTemp`\n- `transitionTime`\n- `alert`\n- `effect`\n- `incrementBrightness`\n- `incrementHue`\n- `incrementSaturation`\n- `incrementXy`\n- `incrementColorTemp`\n\n*Note: See further above for details on `Light` attributes and state*\n\n#### client.lights.delete - Delete a light\n\nRemove a light from the bridge with `client.lights.delete`. This will accept\neither an id or a `Light` object.\n\n```js\nclient.lights.delete(4)\n  .then(() =\u003e {\n    console.log('Light was deleted');\n  })\n  .catch(error =\u003e {\n    console.log('Light may have been removed already, or does not exist');\n    console.log(error.stack);\n  });\n```\n\n### Groups\n\nThe Philips Hue bridge offers the convenience of grouping lights. Rather than\nsetting individual light brightness, color, and other options, you can apply the\nsame changes on a group and have it applied to all linked lights. Huejay\nprovides a complete interface for managing groups on the bridge.\n\nGroups may also represent multisource luminaires. Philips offers several products\nwhich consist of several color changing lights. Upon registering one of these\nproducts with the bridge, a new group is created which represents the logical\ngrouping of the included lights. Huejay offers a simple means of retrieving\nluminaire production information, as well as configuration of these high-end\nfixtures.\n\n#### client.groups.getAll - Get all groups\n\nUse `client.groups.getAll` to retrieve all groups created on the bridge. This\ncommand eventually returns an array of `Group` objects. See further below for\n`Group` object information.\n\n```js\nclient.groups.getAll()\n  .then(groups =\u003e {\n    for (let group of groups) {\n      console.log(`Group [${group.id}]: ${group.name}`);\n      console.log(`  Type: ${group.type}`);\n      console.log(`  Class: ${group.class}`);\n      console.log('  Light Ids: ' + group.lightIds.join(', '));\n      console.log('  State:');\n      console.log(`    Any on:     ${group.anyOn}`);\n      console.log(`    All on:     ${group.allOn}`);\n      console.log('  Action:');\n      console.log(`    On:         ${group.on}`);\n      console.log(`    Brightness: ${group.brightness}`);\n      console.log(`    Color mode: ${group.colorMode}`);\n      console.log(`    Hue:        ${group.hue}`);\n      console.log(`    Saturation: ${group.saturation}`);\n      console.log(`    X/Y:        ${group.xy[0]}, ${group.xy[1]}`);\n      console.log(`    Color Temp: ${group.colorTemp}`);\n      console.log(`    Alert:      ${group.alert}`);\n      console.log(`    Effect:     ${group.effect}`);\n\n      if (group.modelId !== undefined) {\n        console.log(`  Model Id: ${group.modelId}`);\n        console.log(`  Unique Id: ${group.uniqueId}`);\n        console.log('  Model:');\n        console.log(`    Id:           ${group.model.id}`);\n        console.log(`    Manufacturer: ${group.model.manufacturer}`);\n        console.log(`    Name:         ${group.model.name}`);\n        console.log(`    Type:         ${group.model.type}`);\n      }\n\n      console.log();\n    }\n  });\n```\n\nAs demonstrated in the example above, group attributes, state, and actions are available\nvia `Group` objects.\n\nHere are the following attributes and state available on `Group`:\n- `id` - Group Id, generated automatically by the bridge\n- `name` - Configurable name for the group\n- `type` - Configurable type of group (e.g. LightGroup, Luminaire, LightSource, Room)\n- `class` - When `type` is set to `Room`, a class (see below) is available and configurable (e.g. Living room, Office)\n- `lightIds` - An array of light ids associated with the group\n- `modelId` - Available only for multisource luminaires, this is the model id of the fixture\n- `uniqueId` - Available only for multisource luminaires, this is the unique id of the fixture\n- `model` - Available when `modelId` is present, a `GroupModel` object that contains details about the model\n- `anyOn` - True if any lights in the group are on, false if none are on\n- `allOn` - True if all lights in the group are on, false if not\n\nSimilar to `Light` objects, `Group` objects provide action options for\nthe lights associated with the group:\n- `on` - `true` for lights on, `false` if not, configurable\n- `brightness` - Configurable brightness for the lights (value from 0 to 254)\n- `colorMode` - Color mode group is respecting (e.g. ct, xy, hs)\n- `hue` - Configurable hue of the lights (value from 0 to 65535)\n- `saturation` - Configurable saturation of the lights, compliments `hue` (value from 0 to 254)\n- `xy` - Configurable CIE x and y coordinates (value is an array containing x and y values)\n- `colorTemp` - Configurable Mired Color temperature of the lights (value from 153 to 500)\n- `transitionTime` - Configurable temporary value which eases transition of an effect (value in seconds, 0 for instant, 5 for five seconds)\n- `alert` - Configurable alert effect (e.g. none, select, lselect)\n- `effect` - Configurable effect (e.g. none, colorloop)\n- `scene` - Configurable scene\n\nLike `Light` objects, `Group` action properties are available for incrementing and\ndecrementing values:\n- `incrementBrightness` - Increment or decrement brightness value\n- `incrementHue` - Increment or decrement hue value\n- `incrementSaturation` - Increment or decrement saturation value\n- `incrementXy` - Increment or decrement xy values\n- `incrementColorTemp` - Increment or decrement color temperature value\n\nHuejay maintains a list of Philips Hue supported luminaire models. The `Group`\n`model` attribute returns a `GroupModel` object. This object contains more\ninformation about the model:\n- `id` - Model Id, typically the same value as `Group` `modelId`\n- `manufacturer` - Manufacturer of the model (e.g. Philips)\n- `name` - Name of the model / product (e.g. Hue Beyond Table)\n- `type` - Type of group, typically the same value as `Group` `type`\n\nWhen a `Group`'s `type` is `Room`, the following classes can be associated with the group:\n\nClass        | ...\n------------ | ------------\nLiving room  | Gym\nKitchen      | Hallway\nDining       | Toilet\nBathroom     | Front door\nBedroom      | Garage\nKids bedroom | Terrace\nNursery      | Garden\nRecreation   | Driveway\nOffice       | Other\nCarport      |\n\n*Note: The `client.groups.getAll` command does not return special group 0.\nSee `client.groups.getById` for instructions on retrieving this special group.*\n\n#### client.groups.getById - Get group by id\n\nNeed a specific group? `client.groups.getById` accepts a group id. If a group\nexists with that id, a `Group` object is returned, else a `huejay.Error` is\nthrown.\n\n```js\nclient.groups.getById(3)\n  .then(group =\u003e {\n    console.log('Found group:');\n    console.log(`  Group [${group.id}]: ${group.name}`);\n  })\n  .catch(error =\u003e {\n    console.log('Could not find group');\n    console.log(error.stack);\n  });\n```\n\nA **special group** is available which is accessible via group id **0**. This\ngroup always contains all light ids registered on the bridge. Use this group\nto control all lights at once.\n\n```js\nclient.groups.getById(0)\n  .then(group =\u003e {\n    console.log('Special group 0');\n    console.log('  Light Ids:', group.lightIds.join(', '));\n  });\n```\n\n#### client.groups.create - Create a group\n\nCreating a group is easy using Huejay. Instantiate a new `client.groups.Group`\nobject and set both a name and list of light ids.\n\n```js\nlet group = new client.groups.Group;\ngroup.name     = 'New group';\ngroup.lightIds = [2, 4, 5];\n\nclient.groups.create(group)\n  .then(group =\u003e {\n    console.log(`Group [${group.id}] created`);\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\n*Note: Action is not saved on group creation. You must save the group after\ncreation if action is configured.*\n\n#### client.groups.save - Save a group's attributes and action\n\nYou can modify a `Group`'s attributes and action after creation/retrieval, and\nthen apply the changes on the bridge. Like `Light` objects, Huejay will only\napply deltas when saving groups.\n\nTo apply changes, use `client.groups.save`. The `Group` object is returned upon\nsave completion.\n\n```js\nclient.groups.getById(6)\n  .then(group =\u003e {\n    group.name       = 'Brand new name';\n    group.lightIds   = [4, 6, 8];\n\n    group.on         = true;\n    group.brightness = 254;\n    group.effect     = 'colorloop';\n\n    return client.groups.save(group);\n  })\n  .then(group =\u003e {\n    console.log(`Group [${group.id}] was saved`);\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\nThe following `Group` object attributes and action are configurable:\n- `name`\n- `lightIds`\n- `on`\n- `brightness`\n- `hue`\n- `saturation`\n- `xy`\n- `colorTemp`\n- `transitionTime`\n- `alert`\n- `effect`\n- `incrementBrightness`\n- `incrementHue`\n- `incrementSaturation`\n- `incrementXy`\n- `incrementColorTemp`\n\n#### client.groups.delete - Delete a group\n\nTo delete a group from the bridge, pass a group id or `Group` object to\n`client.groups.delete`.\n\n```js\nclient.groups.delete(3)\n  .then(() =\u003e {\n    console.log('Group was deleted');\n  })\n  .catch(error =\u003e {\n    console.log('Group may have been removed already, or does not exist');\n    console.log(error.stack);\n  });\n```\n\n*Note: It is not possible to delete multisource groups. Expect a `huejay.Error`\nto be thrown if attempting to do so.*\n\n### Schedules\n\nHuejay makes it extremely simple to add scheduling to your bridge. Huejay is\nthe only client that abstracts the complicated bits of configuring commands and\ntimers for scheduled operations.\n\n#### client.schedules.getAll - Retrieve all schedules\n\nRetrieve all registered schedules on the bridge with `client.schedules.getAll`.\nThis command eventually returns a list of `Schedule` objects.\n\n```js\nclient.schedules.getAll()\n  .then(schedules =\u003e {\n    for (let schedule of schedules) {\n      console.log(`Schedule [${schedule.id}]: ${schedule.name}`);\n      console.log(`  Description: ${schedule.description}`);\n      console.log(`  Created: ${schedule.created}`);\n      console.log(`  Local time: ${schedule.localTime}`);\n      console.log(`  Status: ${schedule.status}`);\n      console.log(`  Auto delete: ${Boolean(schedule.autoDelete)}`);\n      console.log(`  Action:`);\n      console.log(`    Method: ${schedule.action.method}`);\n      console.log(`    Address: ${schedule.action.address}`);\n      console.log(`    Body: ${JSON.stringify(schedule.action.body)}`);\n      console.log();\n    }\n  });\n```\n\n`Schedule` objects are composed of the following attributes:\n- `id` - Schedule Id, generated and assigned by the bridge on creation\n- `name` - Name for the schedule, configurable\n- `description` - Description for the schedule, configurable\n- `created` - Date when schedule was created\n- `localTime` - Configurable scheduled time, configurable, behavior differs by pattern\n- `status` - `enabled` or `disabled`, configurable\n- `autoDelete` - `true` or `false`, schedule is automatically deleted on expiration when `true`, configurable\n- `action` - Hue native object representing the action to fire for the schedule, configurable\n\n#### client.schedules.getById - Retrieve schedule by id\n\nUse `client.schedules.getById` to retrieve a single schedule by id. A `Schedule`\nobject is eventually returned if found.\n\n```js\nclient.schedules.getById(12)\n  .then(schedule =\u003e {\n    console.log(`Found schedule [${schedule.id}]: ${schedule.name}`);\n  })\n  .catch(error =\u003e {\n    console.log('Could not find schedule');\n    console.log(error.stack);\n  });\n```\n\n#### client.schedules.create - Create a schedule\n\nHuejay is the only Hue client that takes a lot of the guesswork out of manual\nschedule creation. Other clients require you to know how the Philips Hue\nschedules API works in order to create them.\n\n```js\nclient.lights.getById(1)\n  .then(light =\u003e {\n    light.brightness = 1;\n\n    let schedule = new client.schedules.Schedule;\n    schedule.name        = 'Schedule name';\n    schedule.description = 'Sets light brightness to 1 on December 25, 2016 09:00pm';\n    schedule.localTime   = new client.timePatterns.AbsoluteTime('2016-12-25 21:00:00');\n    schedule.action      = new client.actions.ChangeLightState(light);\n\n    return client.schedules.create(schedule);\n  })\n  .then(schedule =\u003e {\n    console.log(`Schedule [${schedule.id}] created`);\n  })\n  .then(error =\u003e console.log(error.stack));\n```\n\nTo simplify configuring `localTime` and `action` attributes on `Schedule`\nobjects, use Huejay's provided time patterns and actions.\n\n##### Time Patterns\n\nHuejay provides a way to easily generating Hue compatible time patterns for\nscheduling. Use these time pattern helpers for generating a compatible `localTime`\nto `Schedule` objects. Be sure to configure your preferred *time zone* of choice\non the bridge.\n\nHere are the time patterns available in Huejay:\n\n###### Time Pattern: Absolute Time\n\nGenerate a specific date. When the bridge reaches this date, the scheduled action\nis invoked.\n\n```js\nschedule.localTime = new client.timePatterns.AbsoluteTime('2016-12-30 12:00:00');\n```\n\n###### Time Pattern: Randomized Time\n\nGenerate a specific date with a random element. When the bridge reaches this date,\nthe scheduled action is invoked randomly between 0 and X seconds.\n\n```js\nschedule.localTime = new client.timePatterns.RandomizedTime(\n  '2016-12-30 12:00:00',\n  3600 // Seconds (3600 is one hour)\n);\n```\n\n###### Time Pattern: Recurring Time\n\nGenerate a recurring weekly date. The bridge will invoke the action on each day\nconfigured, at the specific time set.\n\nThis time pattern accepts a list of days as a combined integer. Huejay provides\nhuman readable equivalents which can be combined via *bitwise or*.\n\n```js\n// Run action on Mondays, Saturdays, Sundays at 09:00:00\nschedule.localTime = new client.timePatterns.RecurringTime(\n  client.timePatterns.RecurringTime.MONDAY | client.timePatterns.RecurringTime.WEEKEND,\n  '09:00:00'\n);\n\n// Available days (these values may move in the future)\nclient.timePatterns.RecurringTime.MONDAY;    // Monday\nclient.timePatterns.RecurringTime.TUESDAY;   // Tuesday\nclient.timePatterns.RecurringTime.WEDNESDAY; // Wednesday\nclient.timePatterns.RecurringTime.THURSDAY;  // Thursday\nclient.timePatterns.RecurringTime.FRIDAY;    // Friday\nclient.timePatterns.RecurringTime.SATURDAY;  // Saturday\nclient.timePatterns.RecurringTime.SUNDAY;    // Sunday\nclient.timePatterns.RecurringTime.WEEKDAY;   // Monday through Friday\nclient.timePatterns.RecurringTime.WEEKEND;   // Saturday and Sunday\n```\n\n###### Time Pattern: Timer\n\nGenerate a timer with the option to repeat.\n\n```js\n// Run action in 1 minute\nschedule.localTime = new client.timePatterns.Timer(60);\n\n// Run action in 30 seconds, cycling through timer 5 times\nschedule.localTime = new client.timePatterns.Timer(30, 5);\n```\n\n##### Actions\n\nHuejay assists in building actions for scheduling and rules. You can access\nthese actions via `client.actions`.\n\nThe following are actions available in Huejay:\n\n###### Action: Change Light State\n\nThis action builds the necessary command for changing light state.\n\n```js\n// Retrieve a Light object and change state\nlight.brightness     = 254;\nlight.colorTemp      = 160;\nlight.transitionTime = 0.5;\n\n// Instantiate action for use with Schedule or Rule objects\n// This will determine changed state for the action\nschedule.action = new client.actions.ChangeLightState(light);\n\n// Instantiate with optional argument to force retrieve state\nschedule.action = new client.actions.ChangeLightState(light, ['brightness']);\n```\n\n###### Action: Change Group Action\n\nThis action helps build command for changing group action.\n\n```js\n// Retrieve a Group object and change action\ngroup.scene = '123456abc';\n\n// Instantiate action for use with Schedule or Rule objects\n// This will determine changed action for the action\nschedule.action = new client.actions.ChangeGroupAction(group);\n\n// Instantiate with optional argument to force retrieve action\nschedule.action = new client.actions.ChangeGroupAction(group, ['scene', 'brightness']);\n```\n\n###### Action: Change Sensor State\n\nThis action assists with changing sensor state.\n\n```js\n// Retrieve a Sensor object and change state\nsensor.state.status = 1;\n\n// Instantiate action for use with Schedule or Rule objects\n// This will determine changed action for the action\nschedule.action = new client.actions.ChangeSensorState(sensor);\n\n// Instantiate with optional argument to force retrieve state\nschedule.action = new client.actions.ChangeSensorState(sensor, ['status']);\n```\n\n#### client.schedules.save - Save schedule\n\nSchedules can be modified and saved. Pass a `Schedule` object to\n`client.schedules.save` to update schedule attributes.\n\n```js\nclient.schedules.getById(12)\n  .then(schedule =\u003e {\n    schedule.name      = 'New schedule name';\n    schedule.localTime = new client.timePatterns.Timer(3600);\n\n    return client.groups.getById(5)\n      .then(group =\u003e {\n        group.scene = '123456abcd';\n\n        schedule.action = new client.actions.ChangeGroupAction(group);\n\n        return client.schedules.save(schedule);\n      });\n  })\n  .catch(error =\u003e console.log(error.stack));\n```\n\nThe following attributes are modifiable:\n- name\n- description\n- localTime\n- status\n- autoDelete\n- action\n\n#### client.schedules.delete - Delete a schedule\n\nAll it takes to delete a schedule from the bridge is to provide either a\nschedule id or a `Schedule` object to the `client.schedules.delete` command.\n\n```js\nclient.schedules.delete('12')\n  .then(() =\u003e {\n    console.log('Schedule was deleted');\n  })\n  .catch(error =\u003e {\n    console.log('Schedule may have been removed already, or does not exist');\n    console.log(error.stack);\n  });\n```\n\n*Note: Schedules may be auto-deleted by the bridge. You can see which schedules\nare configured to auto-delete via `Schedule` object `autoDelete` flag.*\n\n### Scenes\n\nHuejay supports managing scenes on the Philips Hue. Scenes are the best way of\nstoring and recalling commonly used light configurations in your home.\n\n*Note: To recall a scene, set the `scene` attribute on a `Group` object and save.\nAlternatively, use the `client.scenes.recall` command.*\n\n#### client.scenes.getAll - Retrieve all scenes\n\nRetrieves all scenes from the bridge. This command returns an array of `Scene`\nobjects.\n\n```js\nclient.scenes.getAll()\n  .then(scenes =\u003e {\n    for (let scene of scenes) {\n      console.log(`Scene [${scene.id}]: ${scene.name}`);\n      console.log('  Lights:', scene.lightIds.join(', '));\n      console.log();\n    }\n  });\n```\n\n`Scene` objects are composed of the following attributes:\n- `id` - User/application defined scene id (e.g. my-scene-id)\n- `name` - Configurable name\n- `lightIds` - Configurable array of associated light ids\n- `owner` - User who created the scene\n- `recycle` - Configurable option which will auto delete the scene\n- `locked` - If `true`, scene is not deletable as it is being used by another resource\n- `appData` - A configurable object consisting of `version` and `data` properties\n- `picture` - Future field, probably storing picture URL\n- `lastUpdated` - Date when scene was last updated\n- `captureLightState` - Set to `true` to capture current light state for the scene\n- `transitionTime` - Always `null` on access, but can be configured\n\nThe following methods are available on `Scene` objects:\n- `getLightState(lightId)` - Get light state by light id. Values only available by `getById`.\n- `setLightState(lightId, {property: 'value'})` - Set light state by light id.\n\n#### client.scenes.getById - Retrieve scene by id\n\nRetrieve a single scene by id. If the scene is not available, a `huejay.Error`\nis thrown.\n\n```js\nclient.scenes.getById('123456abcdef')\n  .then(scene =\u003e {\n    console.log(`Scene [${scene.id}]: ${scene.name}`);\n    console.log('  Lights:', scene.lightIds.join(', '));\n    console.log();\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\n#### client.scenes.create - Create a scene\n\nScene creation is a breeze. Instantiate a new `client.scenes.Scene`, set a name,\nlightIds, other attributes, and pass to `client.scenes.create`.\n\n```js\nlet scene = new client.scenes.Scene;\nscene.name           = 'Scene name';\nscene.lightIds       = [1, 2, 3];\nscene.recycle        = false;\nscene.appData        = {version: 1, data: 'optional app data'};\nscene.transitionTime = 2;\n\nclient.scenes.create(scene)\n  .then(scene =\u003e {\n    console.log(`Scene [${scene.id}] created...`);\n\n    console.log('  Name:', scene.name);\n    console.log('  Lights:', scene.lightIds.join(', '));\n    console.log('  Owner:', scene.owner);\n    console.log('  Recycle:', scene.recycle);\n    console.log('  Locked:', scene.locked);\n    console.log('  App data:', scene.appData);\n    console.log('  Picture:', scene.picture);\n    console.log('  Last Updated:', scene.lastUpdated);\n    console.log('  Version:', scene.version);\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\nThese `Scene` object attributes can be configured for creation:\n- `name`\n- `lightIds`\n- `recycle`\n- `appData`\n- `captureLightState`\n\n#### client.scenes.save - Save a scene\n\n`Scene` objects can be reconfigured and saved using `client.scenes.save`. Light\nstates can be configured with this command.\n\n```js\nclient.scenes.getById('123456abcdef')\n  .then(scene =\u003e {\n\n    scene.name = 'New scene name';\n    scene.lightIds = [9, 10];\n\n    // Set light state for light id 9\n    scene.setLightState(9, {\n      brightness: 254,\n      colorTemp:  250,\n    });\n\n    // Set light state for light id 10\n    scene.setLightState(10, {\n      brightness: 128,\n      colorTemp:  300,\n      effect:     'colorloop',\n    });\n\n    return client.scenes.save(scene)\n  })\n  .then(scene =\u003e {\n    console.log(`Scene saved...`);\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\n#### client.scenes.recall - Recall a scene\n\nRecall a scene using the convenience command `client.scenes.recall`. Pass a\n`Scene` object or scene id to recall the scene.\n\n```js\nclient.scenes.recall('123456abcdef')\n  .then(() =\u003e {\n    console.log('Scene was recalled');\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\n#### client.scenes.delete - Delete a scene\n\nTo delete a scene, provide a scene id or `Scene` object to\n`client.scenes.delete`.\n\n```js\nclient.scenes.delete('123456abcdef')\n  .then(() =\u003e {\n    console.log('Scene was deleted');\n  })\n  .catch(error =\u003e {\n    console.log('Scene may have been removed already, or does not exist');\n    console.log(error.stack);\n  });\n```\n\n*Note: Scenes being used or referenced by other resources may not be deleted.*\n\n### Sensors\n\nBuy a Hue Tap or Dimmer Switch and want to configure these add-ons without the\nPhilips Hue app? Want to create your own virtual sensors for customizable flags\nand values to invoke light effects? Use Huejay's set of sensor commands to do\nso.\n\n#### client.sensors.scan - Scan for new sensors\n\nThis command is useful for finding new sensors/devices not yet registered with\nyour bridge. Remember to enable pairing mode on the device before calling\n`client.sensors.scan`.\n\nThe bridge scans for new sensors for 30 seconds before stopping.\n\n```js\nclient.sensors.scan()\n  .then(() =\u003e {\n    console.log('Started new sensor scan');\n  });\n```\n\n#### client.sensors.getNew - Get new sensors\n\nAfter running `client.sensors.scan`, you can use `client.sensors.getNew` to\nretrieve a list of newly registered sensors. An array of `Sensor` objects is\nreturned.\n\n```js\nclient.sensors.getNew()\n  .then(sensors =\u003e {\n    console.log('Found new sensors:');\n    for (let sensor of sensors) {\n      console.log(`Sensor [${sensor.id}]:`);\n      console.log('  Unique Id:', sensor.uniqueId);\n      console.log('  Model:',     sensor.model.name);\n    }\n  });\n```\n\nSee below for more information on `Sensor` objects.\n\n#### client.sensors.getAll - Get all sensors\n\nRetrieve all sensors registered to the bridge with `client.sensors.getAll`. This\ncommand will eventually return an array of `Sensor` objects.\n\n```js\nclient.sensors.getAll()\n  .then(sensors =\u003e {\n    for (let sensor of sensors) {\n      console.log(`Sensor [${sensor.id}]: ${sensor.name}`);\n      console.log(`  Type:             ${sensor.type}`);\n      console.log(`  Manufacturer:     ${sensor.manufacturer}`);\n      console.log(`  Model Id:         ${sensor.modelId}`);\n      console.log('  Model:');\n      console.log(`    Id:             ${sensor.model.id}`);\n      console.log(`    Manufacturer:   ${sensor.model.manufacturer}`);\n      console.log(`    Name:           ${sensor.model.name}`);\n      console.log(`    Type:           ${sensor.model.type}`);\n      console.log(`  Software Version: ${sensor.softwareVersion}`);\n      console.log(`  Unique Id:        ${sensor.uniqueId}`);\n      console.log(`  Config:`);\n      console.log(`    On:             ${sensor.config.on}`);\n      console.log(`  State:`);\n      console.log(`    Last Updated:   ${sensor.state.lastUpdated}`);\n      console.log();\n    }\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\n`Sensor` objects consist of the following attributes:\n- `id` - Numerical id of the sensor as registered on the bridge\n- `name` - Configurable name for the sensor\n- `type` - Sensor type (e.g. Daylight, CLIPTemperature, ZGPSwitch)\n- `modelId` - Model Id of the sensor, used for determining `SensorModel`\n- `model` - A `SensorModel` object, containing details about the model\n- `productId` - Unique identifying hardware model (*Note: Not available for all sensors*)\n- `softwareVersion` - Software version of the sensor\n- `softwareConfigId` - Software config id of the light (*Note: Not available for all sensors*)\n- `uniqueId` - Unique Id of the sensor (typically hardware id)\n- `config` - An object with configurable attributes (dependent on sensor type)\n- `state` An object with state attributes (dependent on sensor type)\n\nThe `model` attribute on `Sensor` objects include:\n- `id` - Model Id, typically the same value as `Sensor` `modelId`\n- `manufacturer` - Manufacturer, typically the same value as `Sensor` `manufacturer`\n- `name` - Name of the model / product\n- `type` - Type of the sensor, typically the same value as `Sensor` `type`\n\nSupport values for `Sensor` `type` includes the following:\n- CLIPGenericFlag\n- CLIPGenericStatus\n- CLIPHumidity\n- CLIPOpenClose\n- CLIPPresence\n- CLIPSwitch\n- CLIPTemperature\n\nConfiguration for `Sensor` objects is available via the `config` attribute.\nThis object contains configurable attributes for the sensor, and may be different\nfor each `Sensor` `type`. See [sensor types](lib/SensorType) for available\nconfiguration for each sensor type.\n\nThe following `config` attributes are available for all sensor types:\n- `on` - `true` to enable the sensor, `false` to not, configurable\n\nState for the `Sensor` objects is accessible via the `state` attribute. Like\nconfiguration, the contents of the `state` object may be different for each\n`Sensor` `type`. Rules can be configured to react to sensor state changes.\nSee [sensor types](lib/SensorType) for available state for all supported sensor\ntypes.\n\nThe following `state` attributes are available for all sensor types:\n- `lastUpdated` - Time the sensor state last changed\n\n#### client.sensors.getById - Get sensor by id\n\nA single sensor can be fetched by way of `client.sensors.getById`. If the sensor\nis available A `Sensor` object is returned if one matching the id is found,\notherwise a `huejay.Error` is thrown.\n\n```js\nclient.sensors.getById(1)\n  .then(sensor =\u003e {\n    console.log('Found sensor:');\n    console.log(`  Sensor [${sensor.id}]: ${sensor.name}`);\n  })\n  .catch(error =\u003e {\n    console.log('Could not find sensor');\n    console.log(error.stack);\n  });\n```\n\n#### client.sensors.create - Create a sensor\n\nWant to register your own virtual sensor with the bridge? Use the\n`client.sensors.create` command to create a custom sensor.\n\n```js\nlet sensor = new client.sensors.Sensor;\n\n// Set base sensor attributes\nsensor.name            = 'My temp sensor';\nsensor.modelId         = 'Custom model id';\nsensor.softwareVersion = '0.0.1';\nsensor.type            = 'CLIPTemperature';\nsensor.uniqueId        = '00:11:22';\nsensor.manufacturer    = 'Huejay';\n\n// Set sensor configuration\nsensor.config.on = true;\n\n// Set sensor state\nsensor.state.temperature = 10.2; // Temperature in Celsius\n\n// Create the sensor\nclient.sensors.create(sensor)\n  .then(sensor =\u003e {\n    console.log(`New sensor [${sensor.id}] created`);\n  })\n  .catch(error =\u003e {\n    console.log('Issue creating sensor');\n    console.log(error.stack);\n  });\n```\n\n`config` and `state` attributes differ for each `Sensor` `type`. See above\nfor more details.\n\n#### client.sensors.save - Save a sensor\n\nSensor attributes, configuration, and state can be changed after registration\nwith the bridge (either through `client.sensors.scan` or `client.sensors.create`).\n\nTo save changes made to a `Sensor` object, pass the `Sensor` to `client.sensors.save`.\nHuejay is intelligent enough to save only changed attributes, config, and state.\n\n```js\nclient.sensors.getById(8)\n  .then(sensor =\u003e {\n    sensor.name = 'My updated sensor';\n\n    // Set sensor configuration\n    sensor.config.on = false;\n\n    // Set state\n    sensor.state.temperature = 28.5; // Temperature in Celsius\n\n    return client.sensors.save(sensor);\n  })\n  .then(sensor =\u003e {\n    console.log(`Sensor [${sensor.id}] was saved`);\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\n#### client.sensors.delete - Delete a sensor\n\nDelete a sensor from the bridge by passing an id or `Sensor` object to\n`client.sensors.delete`.\n\n```js\nclient.sensors.delete(8)\n  .then(() =\u003e {\n    console.log('Sensor was deleted');\n  })\n  .catch(error =\u003e {\n    console.log('Sensor may have been removed already, or does not exist');\n    console.log(error.stack);\n  });\n```\n\n### Rules\n\nAfter sensors are registered with the bridge, rules may be created to react\nto sensor state changes. For example, if the temperature changes on a sensor,\nor a button is pressed, you may want a light (or even a group of lights) to\nchange color. Rules satisfy this.\n\n#### client.rules.getAll - Get all rules\n\nUse `client.rules.getAll` to retrieve all rules. This will eventually return\nan array of `Rule` objects.\n\n```js\nclient.rules.getAll()\n  .then(rules =\u003e {\n    for (let rule of rules) {\n      console.log(`Rule [${rule.id}]: ${rule.name}`);\n      console.log(`  Created:         ${rule.created}`);\n      console.log(`  Last Triggered:  ${rule.lastTriggered}`);\n      console.log(`  Times Triggered: ${rule.timesTriggered}`);\n      console.log(`  Owner:           ${rule.owner}`);\n      console.log(`  Status:          ${rule.status}`);\n\n      console.log(`  Conditions:`);\n      for (let condition of rule.conditions) {\n        console.log(`    Address:  ${condition.address}`);\n        console.log(`    Operator: ${condition.operator}`);\n        console.log(`    Value:    ${condition.value}`);\n        console.log();\n      }\n\n      console.log(`  Actions:`);\n      for (let action of rule.actions) {\n        console.log(`    Address: ${action.address}`);\n        console.log(`    Method:  ${action.method}`);\n        console.log(`    Body:    ${JSON.stringify(action.body)}`);\n        console.log();\n      }\n\n      console.log();\n    }\n  });\n```\n\n`Rule` objects contain the following attributes:\n- `id` - Numerical id of the rule, assigned by the bridge on creation\n- `name` - Name of the rule, configurable\n- `lastTriggered` - Date last time rule was triggered\n- `timesTriggered` - Number of times rule was triggered\n- `owner` - User who created the rule\n- `status` - `enabled` or `disabled`, rule is triggerable on `enabled`, configurable\n- `conditions` - An array of objects representing conditions, configurable\n- `actions` - An array of objects representing actions, configurable\n\n`Rule` `conditions` have the following attributes:\n- `address` - The sensor resource/state location for the condition\n- `operator` - The operator for the condition, described below\n- `value` - The value used in conjunction with `operator`\n\n`Rule` `actions` attributes:\n- `address` - The actionable resource location\n- `method` - Type of method for the action (e.g. GET, PUT)\n- `body` - The body of the action, an object\n\nThere are several operators available for use with conditions:\n- `gt` - Greater than: condition is satisfied when sensor state is greater than condition's `value`\n- `lt` - Less than: condition is satisfied when sensor state is less than condition's `value`\n- `eq` - Equal to: condition is satisfied when sensor state equals the condition's `value`\n- `dx` - Changed: condition is satisfied when sensor state changes to a different value\n- `ddx` - Delayed changed: condition is satisfied when sensor delayed state changes to a different value\n- `stable` - Stable: condition is satisfied when sensor state is stable for condition's `value`\n- `not stable` - Not stable: condition is satisfied when sensor state is not stable for condition's `value`\n- `in` - In: Condition is satisfied when time is within start/end time\n- `not in` - Not in: Condition is satisfied when time is not within start/end time\n\n*Note: Huejay abstracts the raw operator values on creating conditions.*\n\n#### client.rules.getById - Get by id\n\nGet a single rule with `client.rules.getById`. A `Rule` object is eventually\nreturned if one is found with the provided id.\n\n```js\nclient.rules.getById(3)\n  .then(rule =\u003e {\n    console.log(`Found: Rule [${rule.id}] - ${rule.name}`);\n  })\n  .catch(error =\u003e console.log(error.stack));\n```\n\n#### client.rules.create - Create a rule\n\nUnlike other clients, Huejay reduces the complexity of creating rules on the\nbridge. Supply a `Rule` object to `client.rules.create` to create a brand new\nrule.\n\nA rule must contain at least 1 condition and 1 action to be created. Use the\n`addCondition` method for adding conditions, and the `addAction` method to add\nactions (using the same actions available for schedules).\n\n```js\n// Retrieve sensor and group for configuring rule\nPromise.all([\n  client.sensors.getById(31),\n  client.groups.getById(0),\n])\n  .then(results =\u003e {\n    let sensor = results[0];\n    let group  = results[1];\n\n    // Configure group light state to off (this will be used for rule action)\n    group.on = false;\n\n    // Build rule\n    let rule = new client.rules.Rule;\n    rule.name   = 'My rule: All lights off on 42';\n    rule.status = 'enabled'; // Optional, defaults to 'enabled'\n\n    // Add 2 conditions to the rule (both must be satisfied to trigger rule)\n    rule.addCondition(sensor).when('buttonEvent').equals(42);\n    rule.addCondition(sensor).when('lastUpdated').changes();\n\n    // Add an action to invoke when rule is triggered\n    rule.addAction(new client.actions.ChangeGroupAction(group));\n\n    return client.rules.create(rule);\n  })\n  .then(rule =\u003e {\n    console.log(`Rule [${rule.id}] created...`);\n  })\n  .catch(error =\u003e console.log(error.stack));\n```\n\nThe `addCondition` helper method makes adding conditions to rules easy. This\nmethod returns a `Condition` object, which includes several chainable\nmethods for configuring a condition. A `Sensor` object is required to use\nthis helper due to the state field needing to be translated to the type's native\nfield format.\n\n```js\n// Greater than (gt) operator\nrule.addCondition(sensor).when('state1').greaterThan(10);\n\n// Less than (lt) operator\nrule.addCondition(sensor).when('state2').lessThan(5);\n\n// Equals (eq) operator\nrule.addCondition(sensor).when('state3').equals(true);\n\n// Changes (dx) operator\nrule.addCondition(sensor).when('state4').changes();\n```\n\n*Note: Rules support a maximum of 8 conditions, and a maximum of 8 actions.\nA minimum of 1 condition and 1 action is required for creating and saving\na rule.*\n\n#### client.rules.save - Save a rule\n\nNeed to make a modification to an existing rule? Use the `client.rules.save`\ncommand to save a rule. More conditions and actions can be added to a rule\nprior to saving as well.\n\n```js\nclient.rules.getById(4)\n  .then(rule =\u003e {\n    // Change rule name and disable\n    rule.name   = 'New rule name';\n    rule.status = 'disabled';\n\n    return client.rules.save(rule);\n  })\n  .catch(error =\u003e console.log(error.stack));\n```\n\nThe following `Rule` object attributes can be saved:\n- `name`\n- `status`\n- `conditions`\n- `actions`\n\nIt is possible to clear existing conditions and actions on a rule for providing\na new set of conditions and actions.\n\n```js\nclient.rules.getById(4)\n  .then(rule =\u003e {\n    // Clears conditions on the rule\n    rule.clearConditions();\n\n    // Clears actions on the rule\n    rule.clearActions();\n\n    // Add conditions and actions here.\n  });\n```\n\n#### client.rules.delete - Delete a rule\n\nTo remove a rule, pass either a `Rule` object or a rule id to the\n`client.rules.delete` command.\n\n```js\nclient.rules.delete(3)\n  .then(() =\u003e {\n    console.log('Rule was deleted');\n  })\n  .catch(error =\u003e {\n    console.log('Rule may have been removed already, or does not exist');\n    console.log(error.stack);\n  });\n```\n\n### Resource Links\n\nWant a way to group together various resources on the bridge? Resource Links\nare used to combine various resources (lights, groups, schedules, etc).\n\n*Note: Huejay's API for managing resource links is not yet finalized.*\n\n#### client.resourceLinks.getAll - Get all resource links\n\n`client.resourceLinks.getAll` can be used to retrieve all resource links from\nthe bridge, which will return a list of `ResourceLink` objects via a promise.\n\n```js\nclient.resourceLinks.getAll()\n  .then(resourceLinks =\u003e {\n    for (let resourceLink of resourceLinks) {\n      console.log(`Resource Link [${resourceLink.id}]:`, resourceLink.name);\n      console.log(`  Description: ${resourceLink.description}`);\n      console.log(`  Type: ${resourceLink.type}`);\n      console.log(`  Class Id: ${resourceLink.classId}`);\n      console.log(`  Owner: ${resourceLink.owner}`);\n      console.log(`  Recycle: ${resourceLink.recycle}`);\n      console.log(`  Links: ${resourceLink.links}`);\n      console.log();\n    }\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\n#### client.resourceLinks.getById - Get by id\n\nTo retrieve a single resource link, use `client.resourceLinks.getById`. This command\nwill eventually a return a `ResourceLink` object if found by provided resource\nlink id.\n\n```js\nclient.resourceLinks.getById(12345)\n  .then(resourceLink =\u003e {\n    console.log(`Found: Resource Link [${resourceLink.id}] - ${resourceLink.name}`);\n  })\n  .catch(error =\u003e console.log(error.stack));\n```\n\n#### client.resourceLinks.create - Create a resource link\n\nCreate resource links using the `client.resourceLinks.create` command.\n\n```js\nlet resourceLink = new client.resourceLinks.ResourceLink;\n\n// Set resource link attributes\nresourceLink.name        = 'Resource link name here';\nresourceLink.description = 'Resource link description here';\nresourceLink.classId     = 1;\nresourceLink.links       = ['/groups/1'];\n\n// Create the resource link\nclient.resourceLinks.create(resourceLink)\n  .then(sensor =\u003e {\n    console.log(`New resource link [${resourceLink.id}] created`);\n  })\n  .catch(error =\u003e {\n    console.log('Issue creating resource link');\n    console.log(error.stack);\n  });\n```\n\n#### client.resourceLinks.save - Save a resource link\n\nResource links can be modified. There is a limited set of attributes that\ncan be saved on these objects. Use `client.resourceLinks.save` to save an\nexisting resource link.\n\n```js\nclient.resourceLinks.getById(12345)\n  .then(resourceLink =\u003e {\n    // Change resource link name, description, and link set\n    resourceLink.name        = 'New resource link name';\n    resourceLink.description = 'New description';\n    resourceLink.links       = ['/groups/1', '/groups/2'];\n\n    return client.resourceLinks.save(resourceLink);\n  })\n  .catch(error =\u003e console.log(error.stack));\n```\n\nThe following `ResourceLink` object attributes can be saved:\n- `name`\n- `description`\n- `links`\n\n#### client.resourceLinks.delete - Delete a resource link\n\nResource links can be deleted using the `client.resourceLinks.delete` command.\n\n```js\nclient.resourceLinks.delete(12345)\n  .then(() =\u003e {\n    console.log('Resource link was deleted');\n  })\n  .catch(error =\u003e {\n    console.log('Resource link may have been removed already, or does not exist');\n    console.log(error.stack);\n  });\n```\n\n### Capabilities\n\nGet bridge resource limits and timezones.\n\n#### client.capabilities.lights\n\nRetrieve bridge light limits with the command `client.capabilities.lights`.\nThis command will eventually return an object describe the limits of the bridge\naround the light resource. \n\n```js\nclient.capabilities.lights()\n  .then(lights =\u003e {\n    console.log('Lights:');\n    console.log(`  Available light slots: ${lights.available}`);\n  })\n  .catch(error =\u003e {\n    console.log(error.stack);\n  });\n```\n\nYou can retrieve additional information about other bridge capabilities with\nthe following commands:\n- `client.capabilities.sensors`\n- `client.capabilities.groups`\n- `client.capabilities.scenes`\n- `client.capabilities.schedules`\n- `client.capabilities.rules`\n- `client.capabilities.resourceLinks`\n\n#### client.capabilities.getTimeZones\n\nRetrieve a list of supported time zones by calling `client.capabilities.getTimeZones`.\n\n```js\nclient.capabilities.getAll()\n  .then(timeZones =\u003e {\n    for (let timeZone of timeZones) {\n      console.log(timeZone);\n    }\n  });\n```\n\n### Time Zones\n\nThe Philips Hue bridge supports configuring a local time zone. This is useful\nfor scheduling functions. Numerous time zones are registered on the bridge for\nretrieval.\n\n#### client.timeZones.getAll - Get all time zones\n\nYou can retrieve a list of supported time zones by calling\n`client.timeZones.getAll`. This will return an array of string values.\n\n```js\nclient.timeZones.getAll()\n  .then(timeZones =\u003e {\n    for (let timeZone of timeZones) {\n      console.log(timeZone);\n    }\n  });\n```\n\n## Examples\n\nWant to see more examples? View them in the [examples](examples) directory included\nin this repository.\n\n## Logo\n\nHuejay's initial logo was designed by scorpion6 on Fiverr. Font used is Lato Bold.\n\n## Additional Resources\n\nLooking for more Philips Hue resources?\n- [Philips Hue Product Page](http://www2.meethue.com/en-us/)\n- [Philips Hue Store](https://www.store.meethue.com/us)\n- [Hue Portal](https://my.meethue.com/en-us/)\n- [Philips Hue Official Documentation](http://www.developers.meethue.com)\n- [Philips Hue Release Notes](http://www2.meethue.com/en-us/release-notes/)\n- [Reddit Hue Subreddit](https://www.reddit.com/r/hue)\n- [SqMK's Philips Hue client for PHP](https://github.com/sqmk/Phue)\n\n## License\n\nThis software is licensed under the MIT License. [View the license](LICENSE).\n\nCopyright © 2015-2016 [Michael K. Squires](http://sqmk.com)\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqmk%2Fhuejay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsqmk%2Fhuejay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsqmk%2Fhuejay/lists"}