[
  {
    "path": ".gitignore",
    "content": "/node_modules\n/npm-debug.log\n/package-lock.json\n/benchmark\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\n\nnode_js:\n    - \"6.14.4\"\n    - \"8.12.0\"\n    - \"10.10.0\"\n\nscript:\n    - npm run test\n\nnotifications:\n    email: false\n\nsudo: false\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015, 2016 Michael K. Squires\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <img src=\"https://cdn.rawgit.com/sqmk/huejay/db9081ee1a22acf77abc93cbd3f2e8f6d20ee16b/media/huejay.svg\" alt=\"Huejay\" />\n</p>\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 => {\n    for (let bridge of bridges) {\n      console.log(`Id: ${bridge.id}, IP: ${bridge.ip}`);\n    }\n  })\n  .catch(error => {\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 => {\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 => {\n    console.log(`New user created - Username: ${user.username}`);\n  })\n  .catch(error => {\n    if (error instanceof huejay.Error && 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 => {\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 => {\n    console.log(`Username: ${user.username}`);\n  });\n  .catch(error => {\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 => {\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(() => {\n    console.log('User was deleted');\n  })\n  .catch(error => {\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(() => {\n    console.log('Successful connection');\n  })\n  .catch(error => {\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(() => {\n    console.log('Successful authentication');\n  })\n  .catch(error => {\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 => {\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 => {\n    // Change bridge's name\n    bridge.name = 'New bridge name';\n\n    return client.bridge.save(bridge);\n  })\n  .then(bridge => {\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(() => {\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(() => {\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 => {\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 => {\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(() => {\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(() => {\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(() => {\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 => {\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 => {\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(() => {\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 => {\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 => {\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 => {\n    console.log('Found light:');\n    console.log(`  Light [${light.id}]: ${light.name}`);\n  })\n  .catch(error => {\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 => {\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 => {\n    console.log(`Updated light [${light.id}]`);\n  })\n  .catch(error => {\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(() => {\n    console.log('Light was deleted');\n  })\n  .catch(error => {\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 => {\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 => {\n    console.log('Found group:');\n    console.log(`  Group [${group.id}]: ${group.name}`);\n  })\n  .catch(error => {\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 => {\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 => {\n    console.log(`Group [${group.id}] created`);\n  })\n  .catch(error => {\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 => {\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 => {\n    console.log(`Group [${group.id}] was saved`);\n  })\n  .catch(error => {\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(() => {\n    console.log('Group was deleted');\n  })\n  .catch(error => {\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 => {\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 => {\n    console.log(`Found schedule [${schedule.id}]: ${schedule.name}`);\n  })\n  .catch(error => {\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 => {\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 => {\n    console.log(`Schedule [${schedule.id}] created`);\n  })\n  .then(error => 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 => {\n    schedule.name      = 'New schedule name';\n    schedule.localTime = new client.timePatterns.Timer(3600);\n\n    return client.groups.getById(5)\n      .then(group => {\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 => 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(() => {\n    console.log('Schedule was deleted');\n  })\n  .catch(error => {\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 => {\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 => {\n    console.log(`Scene [${scene.id}]: ${scene.name}`);\n    console.log('  Lights:', scene.lightIds.join(', '));\n    console.log();\n  })\n  .catch(error => {\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 => {\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 => {\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 => {\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 => {\n    console.log(`Scene saved...`);\n  })\n  .catch(error => {\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(() => {\n    console.log('Scene was recalled');\n  })\n  .catch(error => {\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(() => {\n    console.log('Scene was deleted');\n  })\n  .catch(error => {\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(() => {\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 => {\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 => {\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 => {\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 => {\n    console.log('Found sensor:');\n    console.log(`  Sensor [${sensor.id}]: ${sensor.name}`);\n  })\n  .catch(error => {\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 => {\n    console.log(`New sensor [${sensor.id}] created`);\n  })\n  .catch(error => {\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 => {\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 => {\n    console.log(`Sensor [${sensor.id}] was saved`);\n  })\n  .catch(error => {\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(() => {\n    console.log('Sensor was deleted');\n  })\n  .catch(error => {\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 => {\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 => {\n    console.log(`Found: Rule [${rule.id}] - ${rule.name}`);\n  })\n  .catch(error => 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 => {\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 => {\n    console.log(`Rule [${rule.id}] created...`);\n  })\n  .catch(error => 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 => {\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 => 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 => {\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(() => {\n    console.log('Rule was deleted');\n  })\n  .catch(error => {\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 => {\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 => {\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 => {\n    console.log(`Found: Resource Link [${resourceLink.id}] - ${resourceLink.name}`);\n  })\n  .catch(error => 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 => {\n    console.log(`New resource link [${resourceLink.id}] created`);\n  })\n  .catch(error => {\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 => {\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 => 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(() => {\n    console.log('Resource link was deleted');\n  })\n  .catch(error => {\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 => {\n    console.log('Lights:');\n    console.log(`  Available light slots: ${lights.available}`);\n  })\n  .catch(error => {\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 => {\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 => {\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"
  },
  {
    "path": "examples/.gitignore",
    "content": "/.credentials.json"
  },
  {
    "path": "examples/bridge/get-bridge.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Retrieving bridge (${client.host})...`);\n\nclient.bridge.get()\n  .then(bridge => {\n    console.log(`Bridge:`);\n    console.log(`  Id:                 ${bridge.id}`);\n    console.log(`  Name:               ${bridge.name}`);\n    console.log(`  Model Id:           ${bridge.modelId}`);\n    console.log(`  Factory new:        ${bridge.factoryNew}`);\n    console.log(`  Replaces bridge:    ${bridge.replacesBridgeId}`);\n    console.log(`  Date Store Version: ${bridge.dataStoreVersion}`);\n    console.log(`  Starter Kit Id:     ${bridge.starterKitId}`);\n    console.log();\n\n    console.log(`Model:`);\n    console.log(`  Id:           ${bridge.model.id}`);\n    console.log(`  Manufacturer: ${bridge.model.manufacturer}`);\n    console.log(`  Name:         ${bridge.model.name}`);\n    console.log();\n\n    console.log(`Versions:`);\n    console.log(`  Software Version: ${bridge.softwareVersion}`);\n    console.log(`  API Version:      ${bridge.apiVersion}`);\n    console.log();\n\n    console.log(`Zigbee:`);\n    console.log(`  Channel: ${bridge.zigbeeChannel}`);\n    console.log();\n\n    console.log(`Network details:`);\n    console.log(`  MAC Address:  ${bridge.macAddress}`);\n    console.log(`  IP Address:   ${bridge.ipAddress}`);\n    console.log(`  DHCP enabled: ${bridge.dhcpEnabled}`);\n    console.log(`  Netmask:      ${bridge.netmask}`);\n    console.log(`  Gateway:      ${bridge.gateway}`);\n    console.log();\n\n    console.log(`Proxy:`);\n    console.log(`  Address: ${bridge.proxyAddress}`);\n    console.log(`  Port:    ${bridge.proxyPort}`);\n    console.log();\n\n    console.log(`Time:`);\n    console.log(`  UTC:        ${bridge.utcTime}`);\n    console.log(`  Time zone:  ${bridge.timeZone}`);\n    console.log(`  Local time: ${bridge.localTime}`);\n    console.log();\n\n    console.log(`Portal:`);\n    console.log(`  Services enabled: ${bridge.portalServicesEnabled}`);\n    console.log(`  Connected:        ${bridge.portalConnected}`);\n    console.log();\n\n    console.log(`Functions:`);\n    console.log(`  Link button enabled: ${bridge.linkButtonEnabled}`);\n    console.log(`  Touchlink enabled:   ${bridge.touchlinkEnabled}`);\n    console.log();\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/bridge/is-authenticated.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Testing authentication...');\n\nclient.bridge.isAuthenticated()\n  .then(() => {\n    console.log('Success');\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/bridge/lamp-stealer.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Starting lamp stealer...`);\n\nclient.bridge.touchlink()\n  .then(() => console.log('Touchlink enabled...'))\n  .catch(error => console.log(error.stack));\n"
  },
  {
    "path": "examples/bridge/link-button.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Simulating link button press...`);\n\nclient.bridge.linkButton()\n  .then(() => console.log('Done...'))\n  .catch(error => console.log(error.stack));\n"
  },
  {
    "path": "examples/bridge/ping.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Pinging bridge...');\n\nclient.bridge.ping()\n  .then(() => {\n    console.log('Success');\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/bridge/save-bridge.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Retrieving bridge (${client.host})...`);\n\nclient.bridge.get()\n  .then(bridge => {\n    bridge.name              = `Huejay test ${(new Date()).getSeconds()}`;\n    bridge.timeZone          = 'America/Detroit';\n    bridge.zigbeeChannel     = 20;\n    bridge.dhcpEnabled       = true;\n    bridge.touchlinkEnabled  = true;\n    bridge.linkButtonEnabled = true;\n\n    console.log(`Saving bridge configuration...`);\n\n    return client.bridge.save(bridge);\n  })\n  .then(bridge => {\n    console.log(`Bridge \"${bridge.name}\" saved...`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/capabilities/get-groups.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving group capabilities...');\n\nclient.capabilities.groups()\n  .then(groups => {\n    console.log('Groups:');\n    console.log(`  Available: ${groups.available}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/capabilities/get-lights.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving light capabilities...');\n\nclient.capabilities.lights()\n  .then(lights => {\n    console.log('Lights:');\n    console.log(`  Available: ${lights.available}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/capabilities/get-resource-links.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving resource links capabilities...');\n\nclient.capabilities.resourceLinks()\n  .then(resourceLinks => {\n    console.log('Resource Links:');\n    console.log(`  Available: ${resourceLinks.available}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/capabilities/get-rules.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving rule capabilities...');\n\nclient.capabilities.rules()\n  .then(rules => {\n    console.log('Rules:');\n    console.log(`  Available: ${rules.available}`);\n    console.log(`  Conditions Available: ${rules.conditionsAvailable}`);\n    console.log(`  Actions Available: ${rules.actionsAvailable}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/capabilities/get-scenes.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving scene capabilities...');\n\nclient.capabilities.scenes()\n  .then(scenes => {\n    console.log('Scenes:');\n    console.log(`  Available: ${scenes.available}`);\n    console.log(`  Light States Available: ${scenes.lightStatesAvailable}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/capabilities/get-schedules.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving schedule capabilities...');\n\nclient.capabilities.schedules()\n  .then(schedules => {\n    console.log('Schedules:');\n    console.log(`  Available: ${schedules.available}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/capabilities/get-sensors.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving sensor capabilities...');\n\nclient.capabilities.sensors()\n  .then(sensors => {\n    console.log('Sensors:');\n    console.log(`  Available: ${sensors.available}`);\n    console.log(`  CLIP Available: ${sensors.clipAvailable}`);\n    console.log(`  ZLL Available: ${sensors.zllAvailable}`);\n    console.log(`  ZGP Available: ${sensors.zgpAvailable}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/capabilities/get-time-zones.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving supported time zones...');\n\nclient.capabilities.getTimeZones()\n  .then(timeZones => {\n    console.log('Time Zones:');\n    for (let tz of timeZones) {\n      console.log(`  ${tz}`);\n    }\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/discover.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet huejay = require('../lib/Huejay');\n\nconsole.log('Discovering bridges...');\n\nhuejay.discover()\n  .then(bridges => {\n    if (!bridges.length) {\n      console.log('- No bridges found');\n      return;\n    }\n\n    for (let bridge of bridges) {\n      console.log(`- Id: ${bridge.id}, IP: ${bridge.ip}`);\n    }\n  })\n  .catch(error => {\n    console.log(error.message);\n  });\n"
  },
  {
    "path": "examples/groups/get-groups.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving groups...');\nconsole.log();\n\nclient.groups.getAll()\n  .then(groups => {\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  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/groups/increase-group-hs.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Incrementing group hue/saturation levels...`);\n\nclient.groups.getById(0)\n  .then(group => {\n    console.log(`Saving group...`);\n\n    group.incrementHue        = 6500;\n    group.incrementSaturation = 25;\n    group.transitionTime      = 0.3;\n\n    return client.groups.save(group);\n  })\n  .then(group => {\n    console.log('New hue:', group.hue);\n    console.log('New saturation:', group.saturation);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/groups/manage-group.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Creating group...');\n\nlet group = new client.groups.Group;\ngroup.name     = 'Group name here';\ngroup.lightIds = [1, 2];\n\nclient.groups.create(group)\n  .then(group => {\n    console.log(`New group [${group.id}]:`);\n    console.log(`  Name: ${group.name}`);\n    console.log('  Light Ids:', group.lightIds.join(', '));\n\n    return group.id;\n  })\n  .then(groupId => {\n    console.log(`Retrieving group ${groupId}`);\n\n    return client.groups.getById(groupId);\n  })\n  .then(group => {\n    console.log('Updating group and changing action');\n\n    group.name           = 'New group name here';\n    group.lightIds       = [3, 4, 5, 6];\n    group.on             = true;\n    group.brightness     = 254;\n    group.transitionTime = 0;\n\n    return client.groups.save(group);\n  })\n  .then(group => {\n    console.log('Deleting group');\n\n    return client.groups.delete(group);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/groups/manage-room-group.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Creating group...');\n\nlet group = new client.groups.Group;\ngroup.name     = 'Office group';\ngroup.type     = 'Room';\ngroup.class    = 'Office';\ngroup.lightIds = [4, 5];\n\nclient.groups.create(group)\n  .then(group => {\n    console.log(`New group [${group.id}]:`);\n    console.log(`  Name: ${group.name}`);\n    console.log(`  Type: ${group.type}`);\n    console.log(`  Class: ${group.class}`);\n    console.log('  Light Ids:', group.lightIds.join(', '));\n\n    return group;\n  })\n  .then(group => {\n    console.log('Deleting group');\n\n    return client.groups.delete(group);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/init-client.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet huejay      = require('../lib/Huejay');\nlet credentials = require('./.credentials.json');\n\nlet client = new huejay.Client(credentials);\n\nmodule.exports = client;\n"
  },
  {
    "path": "examples/internet-services/get-internet-services.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Retrieving internet services (${client.host})...`);\n\nclient.internetServices.get()\n  .then(internetServices => {\n    console.log(`Internet services:`);\n    console.log(`  Internet connected: ${internetServices.internetConnected}`);\n    console.log(`  Remote access connected: ${internetServices.remoteAccessConnected}`);\n    console.log(`  Time sync connected: ${internetServices.timeSyncConnected}`);\n    console.log(`  Software update connected: ${internetServices.softwareUpdateConnected}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/lights/get-light.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving light...');\nconsole.log();\n\nclient.lights.getById(8)\n  .then(light => {\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(`    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  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/lights/get-lights.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving lights...');\nconsole.log();\n\nclient.lights.getAll()\n  .then(lights => {\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(`  Product Id:         ${light.productId}`);\n      console.log(`  Software Version:   ${light.softwareVersion}`);\n      console.log(`  Software Config Id: ${light.softwareConfigId}`);\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  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/lights/get-new-lights.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving new lights...');\nconsole.log();\n\nclient.lights.getNew()\n  .then(lights => {\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  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/lights/increase-light-hs.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Incrementing light hue/saturation levels...`);\n\nclient.lights.getById(3)\n  .then(light => {\n    console.log(`Saving light...`);\n\n    light.incrementHue        = 6500;\n    light.incrementSaturation = 25;\n    light.transitionTime      = 5;\n\n    return client.lights.save(light);\n  })\n  .then(light => {\n    console.log('New hue:', light.hue);\n    console.log('New saturation:', light.saturation);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/lights/save-light.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Retrieving light from (${client.host})...`);\n\nclient.lights.getAll()\n  .then(lights => {\n    let light = lights[4];\n\n    light.name = `Name test`;\n    light.on   = true;\n\n    console.log(`Saving light...`);\n\n    return client.lights.save(light);\n  })\n  .then(light => {\n    console.log(`Saved light [${light.id}]`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/lights/start-light-scan.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Starting light scan...');\n\nclient.lights.scan()\n  .then(() => {\n    console.log('Success');\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/portal/get-portal.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Retrieving portal (${client.host})...`);\n\nclient.portal.get()\n  .then(portal => {\n    console.log(`Portal:`);\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    console.log();\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/resource-links/get-resource-link.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving resource link...');\nconsole.log();\n\nclient.resourceLinks.getById(1)\n  .then(resourceLink => {\n    console.log(`Resource Link [${resourceLink.id}]: ${resourceLink.name}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/resource-links/get-resource-links.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving resource links...');\nconsole.log();\n\nclient.resourceLinks.getAll()\n  .then(resourceLinks => {\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 => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/resource-links/manage-resource-link.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Creating resource link...');\n\nlet resourceLink = new client.resourceLinks.ResourceLink;\nresourceLink.name        = 'Resource link name here';\nresourceLink.description = 'Resource link description here';\nresourceLink.classId     = 1;\nresourceLink.links       = ['/groups/1'];\n\nclient.resourceLinks.create(resourceLink)\n  .then(resourceLink => {\n    console.log(`New resource link [${resourceLink.id}]:`);\n\n    return resourceLink.id;\n  })\n  .then(resourceLinkId => {\n    console.log(`Retrieving resource link ${resourceLinkId}`);\n\n    return client.resourceLinks.getById(resourceLinkId);\n  })\n  .then(resourceLink => {\n    console.log('Updating resource link');\n\n    resourceLink.name        = 'New resource link name here';\n    resourceLink.description = 'New resource link description here';\n    resourceLink.links       = ['/groups/2', '/groups/3'];\n\n    return client.resourceLinks.save(resourceLink);\n  })\n  .then(resourceLink => {\n    console.log('Deleting resource link');\n\n    return client.resourceLinks.delete(resourceLink);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/rules/get-rules.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving rules...');\nconsole.log();\n\nclient.rules.getAll()\n  .then(rules => {\n    for (let rule of rules) {\n      console.log(`Rule [${rule.id}]: ${rule.name}`);\n      console.log(`  Last Triggered: ${rule.lastTriggered}`);\n      console.log(`  Created: ${rule.created}`);\n      console.log(`  Times Triggered: ${rule.timesTriggered}`);\n      console.log(`  Owner: ${rule.owner}`);\n      console.log(`  Status: ${rule.status}`);\n      console.log(`  Conditions:`);\n\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  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/rules/manage-rule.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Creating rule...');\n\nlet rule = new client.rules.Rule;\nrule.name   = 'Fake sensor: All lights off';\nrule.status = 'enabled';\n\nPromise.all([\n  client.sensors.getById(31),\n  client.groups.getById(0),\n  client.groups.getById(1),\n])\n  .then(results => {\n    let sensor = results[0];\n    let group  = results[1];\n    let group2 = results[2];\n\n    group.on = false;\n\n    rule.addCondition(sensor).when('buttonEvent').equals(42);\n    rule.addCondition(sensor).when('lastUpdated').changes();\n    rule.addAction(new client.actions.ChangeGroupAction(group));\n\n    return client.rules.create(rule)\n      .then(() => {\n        console.log(`Rule [${rule.id}] created...`);\n\n        rule.name   = 'Fake sensor: Updated name';\n        rule.status = 'disabled';\n        rule.addAction(new client.actions.ChangeGroupAction(group2, ['brightness']));\n\n        console.log('Updating rule...');\n\n        return client.rules.save(rule);\n      })\n      .then(() => {\n        console.log('Deleting rule...');\n\n        return client.rules.delete(rule);\n      });\n  })\n  .catch(error => console.log(error.stack));\n"
  },
  {
    "path": "examples/scenes/get-scenes.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving scenes...');\nconsole.log();\n\nclient.scenes.getAll()\n  .then(scenes => {\n    for (let scene of scenes) {\n      console.log(`Scene [${scene.id}]:`, 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      console.log();\n    }\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/scenes/manage-scene.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Creating scene...');\n\nlet scene = new client.scenes.Scene;\nscene.name           = 'Huejay test';\nscene.lightIds       = [1, 2];\nscene.recycle        = false;\nscene.appData        = {version: 1, data: \"custom data\"};\nscene.transitionTime = 0;\n\nclient.scenes.create(scene)\n  .then(scene => {\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    console.log();\n\n    scene.name = 'New scene name';\n\n    scene.setLightState(1, {\n      brightness: 254,\n      colorTemp: 300,\n    });\n\n    scene.setLightState(2, {\n      brightness: 254,\n      colorTemp: 250\n    });\n\n    return client.scenes.save(scene);\n  })\n  .then(scene => {\n    console.log(`Scene saved...`);\n\n    return client.scenes.delete(scene);\n  })\n  .then(() => {\n    console.log('Scene deleted...');\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/scenes/recall-scene.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Recalling scene...');\n\nclient.scenes.recall('34df1eb80-on-0')\n  .then(() => {\n    console.log('Scene recalled...');\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/scenes/save-scene.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Getting scene...');\n\nclient.scenes.getById('jflowFI1AtKps8d')\n  .then(scene => {\n    scene.setLightState(10, {\n      brightness: 254,\n      colorTemp: 300,\n    });\n\n    scene.setLightState(9, {\n      brightness: 254,\n      colorTemp: 250\n    });\n\n    return client.scenes.save(scene)\n  })\n  .then(scene => {\n    console.log(`Scene saved...`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/schedules/get-schedules.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving schedules...');\nconsole.log();\n\nclient.schedules.getAll()\n  .then(schedules => {\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(`  Command:`);\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  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/schedules/manage-schedule.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\n// Get light\nclient.lights.getById(1)\n  .then(light => {\n    console.log('Light found...');\n\n    light.brightness = 1;\n\n    let schedule = new client.schedules.Schedule;\n    schedule.name        = 'Huejay test';\n    schedule.description = 'Setting light brightness to 1 in 10 seconds';\n    schedule.localTime   = new client.timePatterns.Timer(10);\n    schedule.autoDelete  = true;\n    schedule.action      = new client.actions.ChangeLightState(light, ['brightness']);\n\n    console.log('Creating schedule with light...');\n\n    return client.schedules.create(schedule);\n  })\n  .then(schedule => {\n    console.log(`Schedule created: ${schedule.id}`);\n\n    console.log('Saving schedule');\n    schedule.name = 'New name';\n\n    return client.schedules.save(schedule);\n  })\n  .then(schedule => {\n    console.log('Saved schedule');\n\n    console.log('Retrieving schedule');\n\n    return client.schedules.getById(schedule.id);\n  })\n  .then(schedule => {\n    console.log(`Schedule [${schedule.id}]: ${schedule.name}`);\n\n    return client.schedules.delete(schedule);\n  })\n  .then(() => {\n    console.log(`Schedule deleted`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/sensors/create-switch.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Creating sensor...');\n\nlet sensor = new client.sensors.Sensor;\nsensor.name            = 'Switch test';\nsensor.modelId         = 'Sensormodel';\nsensor.softwareVersion = '1.2.3';\nsensor.type            = 'CLIPSwitch';\nsensor.uniqueId        = '123.456.789';\nsensor.manufacturer    = 'Huejay';\n\nsensor.config.on         = true;\nsensor.state.buttonEvent = 69;\n\nclient.sensors.create(sensor)\n  .then(sensor => {\n    console.log(`New sensor [${sensor.id}]: ${sensor.name}`);\n    console.log(`  Type: ${sensor.type}`);\n    console.log(`  Model Id: ${sensor.modelId}`);\n    console.log(`  Manufacturer: ${sensor.manufacturer}`);\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(`    Button Event: ${sensor.state.buttonEvent}`);\n    console.log();\n  })\n  .catch(error => console.log(error.stack));\n"
  },
  {
    "path": "examples/sensors/get-sensors.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving sensors...');\nconsole.log();\n\nclient.sensors.getAll()\n  .then(sensors => {\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(`  Product Id:         ${sensor.productId}`);\n      console.log(`  Software Version:   ${sensor.softwareVersion}`);\n      console.log(`  Software Config Id: ${sensor.softwareConfigId}`);\n      console.log(`  Unique Id:          ${sensor.uniqueId}`);\n      console.log(`  Config:`);\n      console.log(`    On:               ${sensor.config.on}`);\n      console.log(`  State:`);\n      for (let state in sensor.state.stateMap) {\n        console.log(`    ${state}: ${sensor.state[state]}`);\n      }\n      console.log();\n    }\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/sensors/manage-sensor.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Creating sensor...');\n\nlet sensor = new client.sensors.Sensor;\nsensor.name            = 'Sensor name here';\nsensor.modelId         = 'Sensormodel';\nsensor.softwareVersion = '1.2.3';\nsensor.type            = 'CLIPTemperature';\nsensor.uniqueId        = '123.456.789';\nsensor.manufacturer    = 'Huejay';\n\nsensor.config.on         = false;\nsensor.state.temperature = 10.2;\n\nclient.sensors.create(sensor)\n  .then(sensor => {\n    console.log(`New sensor [${sensor.id}]: ${sensor.name}`);\n    console.log(`  Type: ${sensor.type}`);\n    console.log(`  Model Id: ${sensor.modelId}`);\n    console.log(`  Manufacturer: ${sensor.manufacturer}`);\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(`    Temperature: ${sensor.state.temperature}`);\n    console.log();\n\n    console.log(`Retrieving sensor ${sensor.id}`);\n\n    return client.sensors.getById(sensor.id);\n  })\n  .then(sensor => {\n    console.log('Updating sensor and changing state');\n\n    sensor.name = 'New sensor name here';\n\n    sensor.config.on = false;\n    sensor.state.temperature = 28.5;\n\n    return client.sensors.save(sensor);\n  })\n  .then(sensor => {\n    console.log('Deleting sensor');\n\n    return client.sensors.delete(sensor);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/sensors/update-switch.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Updating sensor...');\n\nclient.sensors.getById(31)\n  .then(sensor => {\n    sensor.state.buttonEvent = 42;\n\n    return client.sensors.save(sensor);\n  })\n  .catch(error => console.log(error.stack));\n"
  },
  {
    "path": "examples/software-update/check-for-software-updates.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Checking for software update (${client.host})...`);\n\nclient.softwareUpdate.check()\n  .then(() => {\n    console.log('Retrieving software update details...');\n\n    return client.softwareUpdate.get();\n  })\n  .then(softwareUpdate => {\n    console.log(`  Checking: ${softwareUpdate.checkingEnabled}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/software-update/disable-install-notification.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Disabling install notification (${client.host})...`);\n\nclient.softwareUpdate.disableInstallNotification()\n  .then(() => {\n    console.log('Retrieving software update details...');\n\n    return client.softwareUpdate.get();\n  })\n  .then(softwareUpdate => {\n    console.log(`  Install notification: ${softwareUpdate.installNotificationEnabled}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/software-update/get-software-update.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Retrieving software update details (${client.host})...`);\n\nclient.softwareUpdate.get()\n  .then(softwareUpdate => {\n    console.log(`  State: ${softwareUpdate.state}`);\n    console.log(`  Checking for update: ${softwareUpdate.checkingEnabled}`);\n    console.log(`  Bridge updates: ${softwareUpdate.bridge}`);\n\n    if (softwareUpdate.lights.length) {\n      console.log('  Lights: ' + softwareUpdate.lights.join(', '));\n    } else {\n      console.log('  Lights: false');\n    }\n\n    if (softwareUpdate.sensors.length) {\n      console.log('  Sensors: ' + softwareUpdate.sensors.join(', '));\n    } else {\n      console.log('  Sensors: false');\n    }\n\n    console.log(`  Release URL: ${softwareUpdate.releaseUrl}`);\n    console.log(`  Release notes: ${softwareUpdate.releaseNotes}`);\n    console.log(`  Notify after installation: ${softwareUpdate.installNotificationEnabled}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/software-update/install-software-updates.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log(`Installing software updates (${client.host})...`);\n\nclient.softwareUpdate.install()\n  .then(() => {\n    console.log('Retrieving software update details...');\n\n    return client.softwareUpdate.get();\n  })\n  .then(softwareUpdate => {\n    console.log(`  State: ${softwareUpdate.state}`);\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/time-zones/get-time-zones.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving supported time zones...');\n\nclient.timeZones.getAll()\n  .then(timeZones => {\n    console.log('Time Zones:');\n    for (let tz of timeZones) {\n      console.log(`  ${tz}`);\n    }\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/users/create-user.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet huejay = require('../../lib/Huejay');\nlet client = require('../init-client');\n\nconsole.log('Attempting to create user.');\nconsole.log('Make sure link button on bridge is pressed.');\nconsole.log('...');\n\nlet user = new client.users.User;\n\nclient.users.create(user)\n  .then(user => {\n    console.log(`New user created:`);\n    console.log(`  Username: ${user.username}`);\n    console.log(`  Device type: ${user.deviceType}`);\n  })\n  .catch(error => {\n    if (error instanceof huejay.Error && error.type === 101) {\n      return console.log(`Link button not pressed. Try again...`);\n    }\n\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/users/delete-user.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Deleting user...');\n\nclient.users.delete('usernamehere')\n  .then(() => {\n    console.log('Success');\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/users/get-user.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving user...');\n\nclient.users.get()\n  .then(user => {\n    if (user === undefined) {\n      return console.log('  Not found.');\n    }\n\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  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "examples/users/get-users.js",
    "content": "#!/usr/bin/env node\n\n'use strict';\n\nlet client = require('../init-client');\n\nconsole.log('Retrieving users...');\nconsole.log();\n\nclient.users.getAll()\n  .then(users => {\n    for (let user of users) {\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      console.log();\n    }\n  })\n  .catch(error => {\n    console.log(error.stack);\n  });\n"
  },
  {
    "path": "lib/Accessor/AbstractAccessor.js",
    "content": "'use strict';\n\n/**\n * Abstract accessor\n */\nclass AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    this.client = client;\n  }\n}\n\nmodule.exports = AbstractAccessor;\n"
  },
  {
    "path": "lib/Accessor/Actions.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\n\n// Action helpers\nlet ChangeLightState  = require('../Action/ChangeLightState');\nlet ChangeGroupAction = require('../Action/ChangeGroupAction');\nlet ChangeSensorState = require('../Action/ChangeSensorState');\n\n/**\n * Actions accessor\n */\nclass Actions extends AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    super(client);\n\n    this.ChangeLightState  = ChangeLightState;\n    this.ChangeGroupAction = ChangeGroupAction;\n    this.ChangeSensorState = ChangeSensorState;\n  }\n}\n\nmodule.exports = Actions;\n"
  },
  {
    "path": "lib/Accessor/Bridge.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\nlet BridgeModel      = require('../Model/Bridge');\n\n// Commands\nlet Ping             = require('../Command/Bridge/Ping');\nlet IsAuthenticated  = require('../Command/Bridge/IsAuthenticated');\nlet EnableLinkButton = require('../Command/Bridge/EnableLinkButton');\nlet EnableTouchlink  = require('../Command/Bridge/EnableTouchlink');\nlet GetBridge        = require('../Command/Bridge/GetBridge');\nlet SaveBridge       = require('../Command/Bridge/SaveBridge');\n\n/**\n * Bridge accessor\n */\nclass Bridge extends AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @return {Client} client Client\n   */\n  constructor(client) {\n    super(client);\n\n    this.Bridge = BridgeModel;\n  }\n\n  /**\n   * Ping the bridge\n   *\n   * @return {Promise} Promise for chaining\n   */\n  ping() {\n    return this.client.invokeCommand(new Ping);\n  }\n\n  /**\n   * Is authenticated\n   *\n   * @return {Promise} Promise for chaining\n   */\n  isAuthenticated() {\n    return this.client.invokeCommand(new IsAuthenticated);\n  }\n\n  /**\n   * Get the bridge\n   *\n   * @return {Promise} Promise for chaining\n   */\n  get() {\n    return this.client.invokeCommand(new GetBridge);\n  }\n\n  /**\n   * Save bridge\n   *\n   * @return {Promise} Promise for chaining\n   */\n  save(bridge) {\n    return this.client.invokeCommand(new SaveBridge(bridge));\n  }\n\n  /**\n   * Enable link button\n   *\n   * @return {Promise} Promise for chaining\n   */\n  linkButton() {\n    return this.client.invokeCommand(new EnableLinkButton);\n  }\n\n  /**\n   * Enable Touchlink\n   *\n   * @return {Promise} Promise for chaining\n   */\n  touchlink() {\n    return this.client.invokeCommand(new EnableTouchlink);\n  }\n}\n\nmodule.exports = Bridge;\n"
  },
  {
    "path": "lib/Accessor/Capabilities.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\n\n// Commands\nlet GetLights        = require('../Command/Capability/GetLights');\nlet GetSensors       = require('../Command/Capability/GetSensors');\nlet GetGroups        = require('../Command/Capability/GetGroups');\nlet GetScenes        = require('../Command/Capability/GetScenes');\nlet GetSchedules     = require('../Command/Capability/GetSchedules');\nlet GetRules         = require('../Command/Capability/GetRules');\nlet GetResourceLinks = require('../Command/Capability/GetResourceLinks');\nlet GetTimeZones     = require('../Command/Capability/GetTimeZones');\n\n/**\n * Capabilities accessor\n */\nclass Capabilities extends AbstractAccessor {\n  /**\n   * Get light capabilities\n   * \n   * @return {Promise} Promise for chaining\n   */\n  lights() {\n    return this.client.invokeCommand(new GetLights);\n  }\n\n  /**\n   * Get sensor capabilities\n   * \n   * @return {Promise} Promise for chaining\n   */\n  sensors() {\n    return this.client.invokeCommand(new GetSensors);\n  }\n\n  /**\n   * Get group capabilities\n   * \n   * @return {Promise} Promise for chaining\n   */\n  groups() {\n    return this.client.invokeCommand(new GetGroups);\n  }\n\n  /**\n   * Get scene capabilities\n   * \n   * @return {Promise} Promise for chaining\n   */\n  scenes() {\n    return this.client.invokeCommand(new GetScenes);\n  }\n\n  /**\n   * Get rule capabilities\n   * \n   * @return {Promise} Promise for chaining\n   */\n  rules() {\n    return this.client.invokeCommand(new GetRules);\n  }\n\n  /**\n   * Get resource links capabilities\n   * \n   * @return {Promise} Promise for chaining\n   */\n  resourceLinks() {\n    return this.client.invokeCommand(new GetResourceLinks);\n  }\n\n  /**\n   * Get schedule capabilities\n   * \n   * @return {Promise} Promise for chaining\n   */\n  schedules() {\n    return this.client.invokeCommand(new GetSchedules);\n  }\n\n  /**\n   * Get time zones\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getTimeZones() {\n    return this.client.invokeCommand(new GetTimeZones);\n  }\n}\n\nmodule.exports = Capabilities;\n"
  },
  {
    "path": "lib/Accessor/Groups.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\nlet Group            = require('../Model/Group');\n\n// Commands\nlet GetGroups       = require('../Command/Group/GetGroups');\nlet GetGroup        = require('../Command/Group/GetGroup');\nlet CreateGroup     = require('../Command/Group/CreateGroup');\nlet SaveGroup       = require('../Command/Group/SaveGroup');\nlet SaveGroupAction = require('../Command/Group/SaveGroupAction');\nlet DeleteGroup     = require('../Command/Group/DeleteGroup');\n\n/**\n * Groups accessor\n */\nclass Groups extends AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    super(client);\n\n    this.Group = Group;\n  }\n\n  /**\n   * Get groups\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getAll() {\n    return this.client.invokeCommand(new GetGroups);\n  }\n\n  /**\n   * Get group by id\n   *\n   * @param {string} id Group Id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getById(id) {\n    return this.client.invokeCommand(new GetGroup(id));\n  }\n\n  /**\n   * Create group\n   *\n   * @param {Group} group Group\n   *\n   * @return {Promise} Promise for chaining\n   */\n  create(group) {\n    return this.client.invokeCommand(new CreateGroup(group));\n  }\n\n  /**\n   * Save group\n   *\n   * @param {Group} group Group\n   *\n   * @return {Promise} Promise for chaining\n   */\n  save(group) {\n    return Promise.all([\n      this.client.invokeCommand(new SaveGroup(group)),\n      this.client.invokeCommand(new SaveGroupAction(group))\n    ]).then(() => {\n      return group;\n    });\n  }\n\n  /**\n   * Delete group\n   *\n   * @param {Group} group Group object or group Id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  delete(group) {\n    return this.client.invokeCommand(new DeleteGroup(group));\n  }\n}\n\nmodule.exports = Groups;\n"
  },
  {
    "path": "lib/Accessor/InternetServices.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\n\n// Commands\nlet GetInternetServices = require('../Command/InternetServices/GetInternetServices');\n\n/**\n * Internet services accessor\n */\nclass InternetServices extends AbstractAccessor {\n  /**\n   * Get internet services\n   *\n   * @return {Promise} Promise for chaining\n   */\n  get() {\n    return this.client.invokeCommand(new GetInternetServices);\n  }\n}\n\nmodule.exports = InternetServices;\n"
  },
  {
    "path": "lib/Accessor/Lights.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\nlet Light            = require('../Model/Light');\n\n// Commands\nlet StartLightScan = require('../Command/Light/StartLightScan');\nlet GetNewLights   = require('../Command/Light/GetNewLights');\nlet GetLights      = require('../Command/Light/GetLights');\nlet GetLight       = require('../Command/Light/GetLight');\nlet SaveLight      = require('../Command/Light/SaveLight');\nlet SaveLightState = require('../Command/Light/SaveLightState');\nlet DeleteLight    = require('../Command/Light/DeleteLight');\n\n/**\n * Lights accessor\n */\nclass Lights extends AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    super(client);\n\n    this.Light = Light;\n  }\n\n  /**\n   * Start light scan\n   *\n   * @return {Promise} Promise for chaining\n   */\n  scan() {\n    return this.client.invokeCommand(new StartLightScan);\n  }\n\n  /**\n   * Get new lights\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getNew() {\n    return this.client.invokeCommand(new GetNewLights);\n  }\n\n  /**\n   * Get all lights\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getAll() {\n    return this.client.invokeCommand(new GetLights);\n  }\n\n  /**\n   * Get light by id\n   *\n   * @param {string} id Light Id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getById(lightId) {\n    return this.client.invokeCommand(new GetLight(lightId));\n  }\n\n  /**\n   * Save light\n   *\n   * @param {Light} light Light\n   *\n   * @return {Promise} Promise for chaining\n   */\n  save(light) {\n    return Promise.all([\n      this.client.invokeCommand(new SaveLight(light)),\n      this.client.invokeCommand(new SaveLightState(light))\n    ]).then(() => {\n      return light;\n    });\n  }\n\n  /**\n   * Delete\n   *\n   * @param {mixed} light Light object or light id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  delete(light) {\n    return this.client.invokeCommand(new DeleteLight(light));\n  }\n}\n\nmodule.exports = Lights;\n"
  },
  {
    "path": "lib/Accessor/Portal.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\n\n// Commands\nlet GetPortal = require('../Command/Portal/GetPortal');\n\n/**\n * Portal accessor\n */\nclass Portal extends AbstractAccessor {\n  /**\n   * Get portal\n   *\n   * @return {Promise} Promise for chaining\n   */\n  get() {\n    return this.client.invokeCommand(new GetPortal);\n  }\n}\n\nmodule.exports = Portal;\n"
  },
  {
    "path": "lib/Accessor/ResourceLinks.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\nlet ResourceLink     = require('../Model/ResourceLink');\n\n// Commands\nlet GetResourceLinks   = require('../Command/ResourceLinks/GetResourceLinks');\nlet GetResourceLink    = require('../Command/ResourceLinks/GetResourceLink');\nlet CreateResourceLink = require('../Command/ResourceLinks/CreateResourceLink');\nlet SaveResourceLink   = require('../Command/ResourceLinks/SaveResourceLink');\nlet DeleteResourceLink = require('../Command/ResourceLinks/DeleteResourceLink');\n\n/**\n * Resource links accessor\n */\nclass ResourceLinks extends AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    super(client);\n\n    this.ResourceLink = ResourceLink;\n  }\n\n  /**\n   * Get resource links\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getAll() {\n    return this.client.invokeCommand(new GetResourceLinks);\n  }\n\n  /**\n   * Get resource link by id\n   *\n   * @param {string} id Resource Link Id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getById(id) {\n    return this.client.invokeCommand(new GetResourceLink(id));\n  }\n\n  /**\n   * Create resource link\n   *\n   * @param {ResourceLink} resourceLink Resource Link\n   *\n   * @return {Promise} Promise for chaining\n   */\n  create(resourceLink) {\n    return this.client.invokeCommand(new CreateResourceLink(resourceLink));\n  }\n\n  /**\n   * Save resource link\n   *\n   * @param {ResourceLink} resourceLink Resource Link\n   *\n   * @return {Promise} Promise for chaining\n   */\n  save(resourceLink) {\n    return this.client.invokeCommand(new SaveResourceLink(resourceLink));\n  }\n\n  /**\n   * Delete resource link\n   *\n   * @param {ResourceLink} resourceLink Resource Link object or resource link Id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  delete(resourceLink) {\n    return this.client.invokeCommand(new DeleteResourceLink(resourceLink));\n  }\n}\n\nmodule.exports = ResourceLinks;\n"
  },
  {
    "path": "lib/Accessor/Rules.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\nlet Rule             = require('../Model/Rule');\nlet Condition        = require('../Model/Condition');\n\n// Commands\nlet GetRules   = require('../Command/Rule/GetRules');\nlet GetRule    = require('../Command/Rule/GetRule');\nlet CreateRule = require('../Command/Rule/CreateRule');\nlet SaveRule   = require('../Command/Rule/SaveRule');\nlet DeleteRule = require('../Command/Rule/DeleteRule');\n\n/**\n * Rules accessor\n */\nclass Rules extends AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    super(client);\n\n    this.Rule      = Rule;\n    this.Condition = Condition;\n  }\n\n  /**\n   * Get all rules\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getAll() {\n    return this.client.invokeCommand(new GetRules);\n  }\n\n  /**\n   * Get rule by id\n   *\n   * @param {string} id Id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getById(id) {\n    return this.client.invokeCommand(new GetRule(id));\n  }\n\n  /**\n   * Create rule\n   *\n   * @param {Rule} rule Rule\n   *\n   * @return {Promise} Promise for chaining\n   */\n  create(rule) {\n    return this.client.invokeCommand(new CreateRule(rule));\n  }\n\n  /**\n   * Save rule\n   *\n   * @param {Rule} rule Rule\n   *\n   * @return {Promise} Promise for chaining\n   */\n  save(rule) {\n    return this.client.invokeCommand(new SaveRule(rule));\n  }\n\n  /**\n   * Delete rule\n   *\n   * @param {mixed} rule Rule or rule id\n   *\n   * @return {[type]} [description]\n   */\n  delete(rule) {\n    return this.client.invokeCommand(new DeleteRule(rule));\n  }\n}\n\nmodule.exports = Rules;\n"
  },
  {
    "path": "lib/Accessor/Scenes.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\nlet Scene            = require('../Model/Scene');\n\n// Commands\nlet GetScenes           = require('../Command/Scene/GetScenes');\nlet GetSceneById        = require('../Command/Scene/GetSceneById');\nlet CreateScene         = require('../Command/Scene/CreateScene');\nlet SaveScene           = require('../Command/Scene/SaveScene');\nlet SaveSceneLightState = require('../Command/Scene/SaveSceneLightState');\nlet RecallScene         = require('../Command/Scene/RecallScene');\nlet DeleteScene         = require('../Command/Scene/DeleteScene');\n\n/**\n * Scenes accessor\n */\nclass Scenes extends AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    super(client);\n\n    this.Scene = Scene;\n  }\n\n  /**\n   * Get scenes\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getAll() {\n    return this.client.invokeCommand(new GetScenes);\n  }\n\n\n  /**\n   * Get by id\n   *\n   * @param {string} sceneId Scene Id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getById(sceneId) {\n    return this.client.invokeCommand(new GetSceneById(sceneId));\n  }\n\n  /**\n   * Create scene\n   *\n   * @param {Scene} scene Scene\n   *\n   * @return {Promise} Promise for chaining\n   */\n  create(scene) {\n    return this.client.invokeCommand(new CreateScene(scene));\n  }\n\n  /**\n   * Save scene\n   *\n   * @param {Scene} scene Scene\n   *\n   * @return {Promise} Promise for chaining\n   */\n  save(scene) {\n    return Promise.all([\n      this.client.invokeCommand(new SaveScene(scene)),\n      this.client.invokeCommand(new SaveSceneLightState(scene))\n    ]).then(() => {\n      return scene;\n    });\n  }\n\n  /**\n   * Recall scene\n   *\n   * @param {mixed} scene Scene object or scene id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  recall(scene) {\n    return this.client.invokeCommand(new RecallScene(scene));\n  }\n\n  /**\n   * Delete scene\n   *\n   * @param {mixed} scene Scene object or scene id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  delete(scene) {\n    return this.client.invokeCommand(new DeleteScene(scene));\n  }\n}\n\nmodule.exports = Scenes;\n"
  },
  {
    "path": "lib/Accessor/Schedules.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\nlet Schedule         = require('../Model/Schedule');\n\n// Commands\nlet GetSchedules   = require('../Command/Schedule/GetSchedules');\nlet GetSchedule    = require('../Command/Schedule/GetSchedule');\nlet CreateSchedule = require('../Command/Schedule/CreateSchedule');\nlet SaveSchedule   = require('../Command/Schedule/SaveSchedule');\nlet DeleteSchedule = require('../Command/Schedule/DeleteSchedule');\n\n/**\n * Schedules accessor\n */\nclass Schedules extends AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    super(client);\n\n    this.Schedule = Schedule;\n  }\n\n  /**\n   * Get all schedules\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getAll() {\n    return this.client.invokeCommand(new GetSchedules);\n  }\n\n  /**\n   * Get schedule\n   *\n   * @param {string} id Schedule Id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getById(id) {\n    return this.client.invokeCommand(new GetSchedule(id));\n  }\n\n  /**\n   * Create schedule\n   *\n   * @param {Schedule} schedule Schedule\n   *\n   * @return {Promise} Promise for chaining\n   */\n  create(schedule) {\n    return this.client.invokeCommand(\n      new CreateSchedule(schedule)\n    );\n  }\n\n  /**\n   * Save schedule\n   *\n   * @param {Schedule} schedule Schedule\n   *\n   * @return {Promise} Promise for chaining\n   */\n  save(schedule) {\n    return this.client.invokeCommand(\n      new SaveSchedule(schedule)\n    );\n  }\n\n  /**\n   * Delete schedule\n   *\n   * @param {mixed} Schedule object or schedule Id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  delete(schedule) {\n    return this.client.invokeCommand(new DeleteSchedule(schedule));\n  }\n}\n\nmodule.exports = Schedules;\n"
  },
  {
    "path": "lib/Accessor/Sensors.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\nlet Sensor           = require('../Model/Sensor');\n\n// Commands\nlet StartSensorScan  = require('../Command/Sensor/StartSensorScan');\nlet GetNewSensors    = require('../Command/Sensor/GetNewSensors');\nlet GetSensors       = require('../Command/Sensor/GetSensors');\nlet GetSensor        = require('../Command/Sensor/GetSensor');\nlet CreateSensor     = require('../Command/Sensor/CreateSensor');\nlet SaveSensor       = require('../Command/Sensor/SaveSensor');\nlet SaveSensorState  = require('../Command/Sensor/SaveSensorState');\nlet SaveSensorConfig = require('../Command/Sensor/SaveSensorConfig');\nlet DeleteSensor     = require('../Command/Sensor/DeleteSensor');\n\n/**\n * Sensors accessor\n */\nclass Sensors extends AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    super(client);\n\n    this.Sensor = Sensor;\n  }\n\n  /**\n   * Scan for new sensors\n   *\n   * @return {Promise} Promise for chaining\n   */\n  scan() {\n    return this.client.invokeCommand(new StartSensorScan);\n  }\n\n  /**\n   * Get new sensors\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getNew() {\n    return this.client.invokeCommand(new GetNewSensors);\n  }\n\n  /**\n   * Get all sensors\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getAll() {\n    return this.client.invokeCommand(new GetSensors);\n  }\n\n  /**\n   * Get sensor by id\n   *\n   * @param {mixed} id Sensor Id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getById(id) {\n    return this.client.invokeCommand(new GetSensor(id));\n  }\n\n  /**\n   * Create sensor\n   *\n   * @param {Sensor} sensor Sensor\n   *\n   * @return {Promise} Promise for chaining\n   */\n  create(sensor) {\n    return this.client.invokeCommand(new CreateSensor(sensor));\n  }\n\n  /**\n   * Save sensor\n   *\n   * @param {Sensor} sensor Sensor\n   *\n   * @return {Promise} Promise for chaining\n   */\n  save(sensor) {\n    return Promise.all([\n      this.client.invokeCommand(new SaveSensor(sensor)),\n      this.client.invokeCommand(new SaveSensorState(sensor)),\n      this.client.invokeCommand(new SaveSensorConfig(sensor))\n    ]).then(() => {\n      return sensor;\n    });\n  }\n\n  /**\n   * Delete sensor\n   *\n   * @param {mixed} sensor Sensor object or sensor id\n   *\n   * @return {Promise} Promise for chaining\n   */\n  delete(sensor) {\n    return this.client.invokeCommand(new DeleteSensor(sensor));\n  }\n}\n\nmodule.exports = Sensors;\n"
  },
  {
    "path": "lib/Accessor/SoftwareUpdate.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\n\n// Commands\nlet GetSoftwareUpdate          = require('../Command/SoftwareUpdate/GetSoftwareUpdate');\nlet CheckForSoftwareUpdates    = require('../Command/SoftwareUpdate/CheckForSoftwareUpdates');\nlet InstallSoftwareUpdates     = require('../Command/SoftwareUpdate/InstallSoftwareUpdates');\nlet DisableInstallNotification = require('../Command/SoftwareUpdate/DisableInstallNotification');\n\n/**\n * Software update accessor\n */\nclass SoftwareUpdate extends AbstractAccessor {\n  /**\n   * Get software update\n   *\n   * @return {Promise} Promise for chaining\n   */\n  get() {\n    return this.client.invokeCommand(new GetSoftwareUpdate);\n  }\n\n  /**\n   * Check for updates\n   *\n   * @return {Promise} Promise for chaining\n   */\n  check() {\n    return this.client.invokeCommand(new CheckForSoftwareUpdates);\n  }\n\n  /**\n   * Install updates\n   *\n   * @return {Promise} Promise for chaining\n   */\n  install() {\n    return this.client.invokeCommand(new InstallSoftwareUpdates);\n  }\n\n  /**\n   * Disable install notification\n   *\n   * @return {Promise} Promise for chaining\n   */\n  disableInstallNotification() {\n    return this.client.invokeCommand(new DisableInstallNotification);\n  }\n}\n\nmodule.exports = SoftwareUpdate;\n"
  },
  {
    "path": "lib/Accessor/TimePatterns.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\n\n// Time patterns\nlet AbsoluteTime   = require('../TimePattern/AbsoluteTime');\nlet RandomizedTime = require('../TimePattern/RandomizedTime');\nlet RecurringTime  = require('../TimePattern/RecurringTime');\nlet Timer          = require('../TimePattern/Timer');\n\n/**\n * Time patterns accessor\n */\nclass TimePatterns extends AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    super(client);\n\n    this.AbsoluteTime   = AbsoluteTime;\n    this.RandomizedTime = RandomizedTime;\n    this.RecurringTime  = RecurringTime;\n    this.Timer          = Timer;\n  }\n}\n\nmodule.exports = TimePatterns;\n"
  },
  {
    "path": "lib/Accessor/TimeZones.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\n\n// Commands\nlet GetTimeZones = require('../Command/TimeZone/GetTimeZones');\n\n/**\n * Time zones accessor\n */\nclass TimeZones extends AbstractAccessor {\n  /**\n   * Get all time zones\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getAll() {\n    return this.client.invokeCommand(new GetTimeZones);\n  }\n}\n\nmodule.exports = TimeZones;\n"
  },
  {
    "path": "lib/Accessor/Users.js",
    "content": "'use strict';\n\nlet AbstractAccessor = require('./AbstractAccessor');\nlet User             = require('../Model/User');\n\n// Commands\nlet GetUsers   = require('../Command/User/GetUsers');\nlet GetUser    = require('../Command/User/GetUser');\nlet CreateUser = require('../Command/User/CreateUser');\nlet DeleteUser = require('../Command/User/DeleteUser');\n\n/**\n * Users accessor\n */\nclass Users extends AbstractAccessor {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    super(client);\n\n    this.User = User;\n  }\n\n  /**\n   * Get all users\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getAll() {\n    return this.client.invokeCommand(new GetUsers);\n  }\n\n  /**\n   * Get currently authed user\n   *\n   * @return {Promise} Promise for chaining\n   */\n  get() {\n    return this.client.invokeCommand(new GetUser(this.client.username));\n  }\n\n  /**\n   * Get user by username\n   *\n   * @param {mixed} username Username or User object\n   *\n   * @return {Promise} Promise for chaining\n   */\n  getByUsername(username) {\n    return this.client.invokeCommand(new GetUser(username));\n  }\n\n  /**\n   * Create user\n   *\n   * @param {User} user User\n   *\n   * @return {Promise} Promise for chaining\n   */\n  create(user) {\n    return this.client.invokeCommand(new CreateUser(user));\n  }\n\n  /**\n   * Delete user\n   *\n   * @param {mixed} user Username or User object\n   *\n   * @return {Promise} Promise for chaining\n   */\n  delete(user) {\n    return this.client.invokeCommand(new DeleteUser(user));\n  }\n}\n\nmodule.exports = Users;\n"
  },
  {
    "path": "lib/Action/AbstractAction.js",
    "content": "'use strict';\n\nlet Error = require('../Error');\n\n/**\n * Abstract action\n */\nclass AbstractAction {\n  /**\n   * Export action\n   */\n  exportAction() {\n    throw new Error({\n      message: 'Action must define exportAction'\n    });\n  }\n}\n\nmodule.exports = AbstractAction;\n"
  },
  {
    "path": "lib/Action/ChangeGroupAction.js",
    "content": "'use strict';\n\nlet AbstractAction = require('./AbstractAction');\nlet GroupUtils     = require('../Command/Group/Utils');\n\nconst GROUP_ACTION_MAP = {\n  on:                  'on',\n  brightness:          'bri',\n  hue:                 'hue',\n  saturation:          'sat',\n  xy:                  'xy',\n  colorTemp:           'ct',\n  alert:               'alert',\n  effect:              'effect',\n  scene:               'scene',\n  transitionTime:      'transitiontime',\n  incrementBrightness: 'bri_inc',\n  incrementHue:        'hue_inc',\n  incrementSaturation: 'sat_inc',\n  incrementXy:         'xy_inc',\n  incrementColorTemp:  'ct_inc',\n};\n\n/**\n * Change group action action\n */\nclass ChangeGroupAction extends AbstractAction {\n  /**\n   * Constructor\n   *\n   * @param {Group} group     Group\n   * @param {array} useAction Action to use\n   */\n  constructor(group, useAction) {\n    super();\n\n    GroupUtils.validateGroup(group);\n\n    this.group     = group;\n    this.useAction = useAction;\n  }\n\n  /**\n   * Export action\n   *\n   * @param {client} client Client\n   *\n   * @return {Object} Action object\n   */\n  exportAction(client, withUsername) {\n    let address = `/groups/${this.group.id}/action`;\n    let body    = {};\n\n    if (this.useAction !== undefined) {\n      for (let key of this.useAction) {\n        if (key in GROUP_ACTION_MAP) {\n          let actionAttribute = GROUP_ACTION_MAP[key];\n          body[actionAttribute] = this.group.action.get(actionAttribute);\n        }\n      }\n    } else {\n      body = this.group.action.getChanged();\n    }\n\n    if (!!withUsername) {\n      address = `/api/${client.username}${address}`;\n    }\n\n    return {\n      method: 'PUT',\n      address,\n      body,\n    }\n  }\n}\n\nmodule.exports = ChangeGroupAction;\n"
  },
  {
    "path": "lib/Action/ChangeLightState.js",
    "content": "'use strict';\n\nlet AbstractAction = require('./AbstractAction');\nlet LightUtils     = require('../Command/Light/Utils');\n\nconst LIGHT_STATE_MAP = {\n  on:                  'on',\n  brightness:          'bri',\n  hue:                 'hue',\n  saturation:          'sat',\n  xy:                  'xy',\n  colorTemp:           'ct',\n  alert:               'alert',\n  effect:              'effect',\n  transitionTime:      'transitiontime',\n  incrementBrightness: 'bri_inc',\n  incrementHue:        'hue_inc',\n  incrementSaturation: 'sat_inc',\n  incrementXy:         'xy_inc',\n  incrementColorTemp:  'ct_inc',\n};\n\n/**\n * Change light state action\n */\nclass ChangeLightState extends AbstractAction {\n  /**\n   * Constructor\n   *\n   * @param {Light} light    Light\n   * @param {array} useState State to use\n   */\n  constructor(light, useState) {\n    super();\n\n    LightUtils.validateLight(light);\n\n    this.light    = light;\n    this.useState = useState;\n  }\n\n  /**\n   * Export action\n   *\n   * @param {client} client Client\n   *\n   * @return {Object} Action object\n   */\n  exportAction(client, withUsername) {\n    let address = `/lights/${this.light.id}/state`;\n    let body    = {};\n\n    if (this.useState !== undefined) {\n      for (let key of this.useState) {\n        if (key in LIGHT_STATE_MAP) {\n          let stateAttribute = LIGHT_STATE_MAP[key];\n          body[stateAttribute] = this.light.state.get(stateAttribute);\n        }\n      }\n    } else {\n      body = this.light.state.getChanged();\n    }\n\n    if (!!withUsername) {\n      address = `/api/${client.username}${address}`;\n    }\n\n    return {\n      method: 'PUT',\n      address,\n      body,\n    }\n  }\n}\n\nmodule.exports = ChangeLightState;\n"
  },
  {
    "path": "lib/Action/ChangeSensorState.js",
    "content": "'use strict';\n\nlet AbstractAction = require('./AbstractAction');\nlet SensorUtils    = require('../Command/Sensor/Utils');\n\n/**\n * Change sensor state action\n */\nclass ChangeSensorState extends AbstractAction {\n  /**\n   * Constructor\n   *\n   * @param {Sensor} sensor   Sensor\n   * @param {array}  useState State to use\n   */\n  constructor(sensor, useState) {\n    super();\n\n    SensorUtils.validateSensor(sensor);\n\n    this.sensor   = sensor;\n    this.useState = useState;\n  }\n\n  /**\n   * Export action\n   *\n   * @param {client} client Client\n   *\n   * @return {Object} Action object\n   */\n  exportAction(client, withUsername) {\n    let address = `/sensors/${this.sensor.id}/state`;\n    let body    = {};\n    let sensorStateMap = this.sensor.state.stateMap;\n\n    if (this.useState !== undefined) {\n      for (let key of this.useState) {\n        if (key in sensorStateMap) {\n          let stateAttribute = sensorStateMap[key];\n          body[stateAttribute] = this.sensor.state.attributes.get(stateAttribute);\n        }\n      }\n    } else {\n      body = this.sensor.state.attributes.getChanged();\n    }\n\n    if (!!withUsername) {\n      address = `/api/${client.username}${address}`;\n    }\n\n    return {\n      method: 'PUT',\n      address,\n      body,\n    }\n  }\n}\n\nmodule.exports = ChangeSensorState;\n"
  },
  {
    "path": "lib/BridgeModel/AbstractBridgeModel.js",
    "content": "'use strict';\n\n/**\n * Abstract bridge model\n */\nclass AbstractBridgeModel {\n  /**\n   * Constructor\n   *\n   * @param {Object} details Bridge model details\n   */\n  constructor(details) {\n    this.details = Object.assign({}, details);\n  }\n\n  /**\n   * Get id of model\n   *\n   * @return {string} Id\n   */\n  get id() {\n    return this.details.id;\n  }\n\n  /**\n   * Get manufacturer\n   *\n   * @return {string} Manufacturer\n   */\n  get manufacturer() {\n    return this.details.manufacturer;\n  }\n\n  /**\n   * Get name of model\n   *\n   * @return {string} Name\n   */\n  get name() {\n    return this.details.name;\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Name\n   */\n  toString() {\n    return this.name;\n  }\n}\n\nmodule.exports = AbstractBridgeModel;\n"
  },
  {
    "path": "lib/BridgeModel/BSB001.js",
    "content": "'use strict';\n\nlet AbstractBridgeModel = require('./AbstractBridgeModel');\n\nconst DETAILS = {\n  id:           'BSB001',\n  manufacturer: 'Philips',\n  name:         'Hue v1',\n};\n\n/**\n * Bridge model: BSB001\n */\nclass BSB001 extends AbstractBridgeModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = BSB001;\n"
  },
  {
    "path": "lib/BridgeModel/BSB002.js",
    "content": "'use strict';\n\nlet AbstractBridgeModel = require('./AbstractBridgeModel');\n\nconst DETAILS = {\n  id:           'BSB002',\n  manufacturer: 'Philips',\n  name:         'Hue v2',\n};\n\n/**\n * Bridge model: BSB002\n */\nclass BSB002 extends AbstractBridgeModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = BSB002;\n"
  },
  {
    "path": "lib/BridgeModel/Factory.js",
    "content": "'use strict';\n\nconst SUPPORTED_BRIDGES = [\n  'BSB001',\n  'BSB002',\n  'Unknown',\n];\n\n/**\n * Factory for Bridge Models\n */\nclass Factory {\n  /**\n   * Create bridge model\n   *\n   * @param {string} modelId Model Id\n   *\n   * @return {AbstractBridgeModel} Bridge model\n   */\n  static createBridgeModel(modelId) {\n    if (SUPPORTED_BRIDGES.indexOf(modelId) === -1) {\n      modelId = 'Unknown';\n    }\n\n    let BridgeModel = require(`./${modelId}`);\n\n    return new BridgeModel;\n  }\n}\n\nmodule.exports = Factory;\n"
  },
  {
    "path": "lib/BridgeModel/Unknown.js",
    "content": "'use strict';\n\nlet AbstractBridgeModel = require('./AbstractBridgeModel');\n\nconst DETAILS = {\n  id:           null,\n  manufacturer: null,\n  name:         null,\n};\n\n/**\n * Bridge model: Unknown\n */\nclass Unknown extends AbstractBridgeModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = Unknown;\n"
  },
  {
    "path": "lib/CapabilityModel/AbstractCapabilityModel.js",
    "content": "'use strict';\n\n/**\n * Abstract capability model\n */\nclass AbstractCapabilityModel {\n  /**\n   * Constructor\n   *\n   * @param {Object} details Capability model details\n   */\n  constructor(details) {\n    this.details = Object.assign({}, details);\n  }\n\n  /**\n   * Available\n   *\n   * @param {int} Available\n   */\n  get available() {\n    return this.details.available;\n  }\n}\n\nmodule.exports = AbstractCapabilityModel;"
  },
  {
    "path": "lib/CapabilityModel/Groups.js",
    "content": "'use strict';\n\nlet AbstractCapabilityModel = require('./AbstractCapabilityModel');\n\n/**\n * Groups capability model\n */\nclass Groups extends AbstractCapabilityModel {}\n\nmodule.exports = Groups;\n"
  },
  {
    "path": "lib/CapabilityModel/Lights.js",
    "content": "'use strict';\n\nlet AbstractCapabilityModel = require('./AbstractCapabilityModel');\n\n/**\n * Lights capability model\n */\nclass Lights extends AbstractCapabilityModel {}\n\nmodule.exports = Lights;\n"
  },
  {
    "path": "lib/CapabilityModel/ResourceLinks.js",
    "content": "'use strict';\n\nlet AbstractCapabilityModel = require('./AbstractCapabilityModel');\n\n/**\n * Resource links capability model\n */\nclass ResourceLinks extends AbstractCapabilityModel {}\n\nmodule.exports = ResourceLinks;\n"
  },
  {
    "path": "lib/CapabilityModel/Rules.js",
    "content": "'use strict';\n\nlet AbstractCapabilityModel = require('./AbstractCapabilityModel');\n\n/**\n * Rules capability model\n */\nclass Rules extends AbstractCapabilityModel {\n    /**\n     * Get conditions available\n     * \n     * @params {int} Available\n     */\n    get conditionsAvailable() {\n        return this.details.conditions.available;\n    }\n\n    /**\n     * Get actions available\n     * \n     * @params {int} Available\n     */\n    get actionsAvailable() {\n        return this.details.actions.available;\n    }\n}\n\nmodule.exports = Rules;\n"
  },
  {
    "path": "lib/CapabilityModel/Scenes.js",
    "content": "'use strict';\n\nlet AbstractCapabilityModel = require('./AbstractCapabilityModel');\n\n/**\n * Scenes capability model\n */\nclass Scenes extends AbstractCapabilityModel {\n    /**\n     * Get light states available\n     * \n     * @params {int} Available\n     */\n    get lightStatesAvailable() {\n        return this.details.lightstates.available;\n    }\n}\n\nmodule.exports = Scenes;\n"
  },
  {
    "path": "lib/CapabilityModel/Schedules.js",
    "content": "'use strict';\n\nlet AbstractCapabilityModel = require('./AbstractCapabilityModel');\n\n/**\n * Schedules capability model\n */\nclass Schedules extends AbstractCapabilityModel {}\n\nmodule.exports = Schedules;\n"
  },
  {
    "path": "lib/CapabilityModel/Sensors.js",
    "content": "'use strict';\n\nlet AbstractCapabilityModel = require('./AbstractCapabilityModel');\n\n/**\n * Sensors capability model\n */\nclass Sensors extends AbstractCapabilityModel {\n    /**\n     * Get clip available\n     * \n     * @params {int} Available\n     */\n    get clipAvailable() {\n        return this.details.clip.available;\n    }\n\n    /**\n     * Get zll available\n     * \n     * @params {int} Available\n     */\n    get zllAvailable() {\n        return this.details.zll.available;\n    }\n\n    /**\n     * Get zgps available\n     * \n     * @params {int} Available\n     */\n    get zgpAvailable() {\n        return this.details.zgp.available;\n    }\n}\n\nmodule.exports = Sensors;\n"
  },
  {
    "path": "lib/Client.js",
    "content": "'use strict';\n\nconst DEFAULT_CONFIG = {\n  host:     undefined,\n  port:     80,\n  username: undefined,\n  timeout:  15000,\n};\n\n/**\n * Client\n *\n * Serves as client to the bridge\n */\nclass Client {\n  /**\n   * Constructor\n   *\n   * @param {Object} config Configuration\n   */\n  constructor(config) {\n    this.config    = Object.assign({}, DEFAULT_CONFIG, config);\n    this.accessors = {};\n  }\n\n  /**\n   * Get host\n   *\n   * @return {string} Host\n   */\n  get host() {\n    return this.config.host;\n  }\n\n  /**\n   * Set host\n   *\n   * @param {string} host Host\n   */\n  set host(host) {\n    this.config.host = host;\n  }\n\n  /**\n   * Get port\n   *\n   * @return {int} Port\n   */\n  get port() {\n    return this.config.port;\n  }\n\n  /**\n   * Set port\n   *\n   * @param {int} port Port\n   */\n  set port(port) {\n    this.config.port = Number(port);\n  }\n\n  /**\n   * Get username\n   *\n   * @return {string} Username\n   */\n  get username() {\n    return this.config.username;\n  }\n\n  /**\n   * Set username\n   *\n   * @param {string} username Username\n   */\n  set username(username) {\n    this.config.username = username;\n  }\n\n  /**\n   * Get timeout\n   *\n   * @return {int} Timeout\n   */\n  get timeout() {\n    return this.config.timeout;\n  }\n\n  /**\n   * Set timeout\n   *\n   * @param {int} timeout Timeout\n   */\n  set timeout(timeout) {\n    this.config.timeout = Number(timeout);\n  }\n\n  /**\n   * Get bridge accessor\n   *\n   * @return {mixed} Bridge accessor\n   */\n  get bridge() {\n    return this.loadAccessor('Bridge');\n  }\n\n  /**\n   * Get portal accessor\n   *\n   * @return {mixed} Portal accessor\n   */\n  get portal() {\n    return this.loadAccessor('Portal');\n  }\n\n  /**\n   * Get internet services\n   *\n   * @return {mixed} Internet services accessor\n   */\n  get internetServices() {\n    return this.loadAccessor('InternetServices');\n  }\n\n  /**\n   * Get sofware update accessor\n   *\n   * @return {mixed} Software update accessor\n   */\n  get softwareUpdate() {\n    return this.loadAccessor('SoftwareUpdate');\n  }\n\n  /**\n   * Get users accessor\n   *\n   * @return {mixed} Users accessor\n   */\n  get users() {\n    return this.loadAccessor('Users');\n  }\n\n  /**\n   * Get lights accessor\n   *\n   * @return {mixed} Lights accessor\n   */\n  get lights() {\n    return this.loadAccessor('Lights');\n  }\n\n  /**\n   * Get groups accessor\n   *\n   * @return {mixed} Groups accessor\n   */\n  get groups() {\n    return this.loadAccessor('Groups');\n  }\n\n  /**\n   * Get scenes accessor\n   *\n   * @return {mixed} Scenes accessor\n   */\n  get scenes() {\n    return this.loadAccessor('Scenes');\n  }\n\n  /**\n   * Get schedules accessor\n   *\n   * @return {mixed} Schedules accessor\n   */\n  get schedules() {\n    return this.loadAccessor('Schedules');\n  }\n\n  /**\n   * Get sensors accessor\n   *\n   * @return {mixed} Sensors accessor\n   */\n  get sensors() {\n    return this.loadAccessor('Sensors');\n  }\n\n  /**\n   * Get rules accessor\n   *\n   * @return {mixed} Rules accessor\n   */\n  get rules() {\n    return this.loadAccessor('Rules');\n  }\n\n  /**\n   * Get actions accessor\n   *\n   * @return {mixed} Actions accessor\n   */\n  get actions() {\n    return this.loadAccessor('Actions');\n  }\n\n  /**\n   * Get time patterns accessor\n   *\n   * @return {mixed} Time patterns accessor\n   */\n  get timePatterns() {\n    return this.loadAccessor('TimePatterns');\n  }\n\n  /**\n   * Get resource links accessor\n   *\n   * @return {mixed} Resource links accessor\n   */\n  get resourceLinks() {\n    return this.loadAccessor('ResourceLinks');\n  }\n\n  /**\n   * Get capabilities accessor\n   * \n   * @return {mixed} Capabilities accessor\n   */\n  get capabilities() {\n    return this.loadAccessor('Capabilities');\n  }\n\n  /**\n   * Get time zones accessor\n   *\n   * @return {mixed} Time zones accessor\n   */\n  get timeZones() {\n    return this.loadAccessor('TimeZones');\n  }\n\n  /**\n   * Load accessor\n   *\n   * @param {string} accessor Accessor name\n   *\n   * @return {mixed} Accessor\n   */\n  loadAccessor(accessor) {\n    if (!this.accessors[accessor]) {\n      let Accessor = require(`./Accessor/${accessor}`);\n\n      this.accessors[accessor] = new Accessor(this);\n    }\n\n    return this.accessors[accessor];\n  }\n\n  /**\n   * Get transport\n   *\n   * @return {Transport} Transport (http)\n   */\n  getTransport() {\n    if (this.transport === undefined) {\n      let Transport = new require('./Transport');\n\n      this.transport = new Transport(this);\n    }\n\n    return this.transport;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {mixed} command Command\n   *\n   * @return {mixed} Result from command\n   */\n  invokeCommand(command) {\n    return command.invoke(this);\n  }\n}\n\nmodule.exports = Client;\n"
  },
  {
    "path": "lib/Command/Bridge/EnableLinkButton.js",
    "content": "'use strict';\n\n/**\n * Enable Link Button command\n *\n * Enable link button\n */\nclass EnableLinkButton {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/config`,\n      data:   {\n        'linkbutton': true\n      }\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = EnableLinkButton;\n"
  },
  {
    "path": "lib/Command/Bridge/EnableTouchlink.js",
    "content": "'use strict';\n\n/**\n * Enable Touchlink command\n *\n * Enable Touchlink\n */\nclass EnableTouchlink {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/config`,\n      data:   {\n        'touchlink': true\n      }\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = EnableTouchlink;\n"
  },
  {
    "path": "lib/Command/Bridge/GetBridge.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get bridge command\n *\n * Get bridge info and configuration\n */\nclass GetBridge {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: client.username !== undefined\n        ? `api/${client.username}/config`\n        : 'api/config'\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Utils.buildBridge(result);\n      });\n  }\n}\n\nmodule.exports = GetBridge;\n"
  },
  {
    "path": "lib/Command/Bridge/IsAuthenticated.js",
    "content": "'use strict';\n\n/**\n * Is authenticated command\n *\n * Determines if user is authenticated to bridge\n */\nclass IsAuthenticated {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      // Time zone retrieval as it requires user and not resource intensive\n      url: `api/${client.username}/info/timezones`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = IsAuthenticated;\n"
  },
  {
    "path": "lib/Command/Bridge/Ping.js",
    "content": "'use strict';\n\n/**\n * Ping command\n *\n * Pings bridge\n */\nclass Ping {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: 'api/config'\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = Ping;\n"
  },
  {
    "path": "lib/Command/Bridge/SaveBridge.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'zigbeechannel',\n  'ipaddress',\n  'dhcp',\n  'netmask',\n  'gateway',\n  'proxyport',\n  'proxyaddress',\n  'timezone',\n  'linkbutton',\n  'touchlink',\n];\n\n/**\n * Save bridge command\n *\n * Saves bridge\n */\nclass SaveBridge {\n  /**\n   * Constructor\n   *\n   * @param {Bridge} bridge Bridge\n   */\n  constructor(bridge) {\n    Utils.validateBridge(bridge);\n\n    this.bridge = bridge;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let promises   = [];\n\n    let attributes = this.bridge.attributes.getChanged();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        promises.push(\n          this.saveBridgeAttribute(\n            client,\n            key,\n            attributes[key]\n          )\n        );\n      }\n    }\n\n    return Promise.all(promises)\n      .then(results => {\n        this.bridge.attributes.resetChanged();\n\n        return this.bridge;\n      });\n  }\n\n  /**\n   * Save bridge attribute\n   *\n   * @param {Client} client    Client\n   * @param {string} attribute Attribute\n   * @param {mixed}  value     Value\n   *\n   * @return {Promise} Promise for chaining\n   */\n  saveBridgeAttribute(client, attribute, value) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/config`,\n      data:   {}\n    };\n\n    options.data[attribute] = value;\n\n    return client.getTransport()\n      .sendRequest(options);\n  }\n}\n\nmodule.exports = SaveBridge;\n"
  },
  {
    "path": "lib/Command/Bridge/Utils.js",
    "content": "'use strict';\n\nlet Bridge = require('../../Model/Bridge');\nlet Error  = require('../../Error');\n\nconst BRIDGE_ATTRIBUTES = [\n  'bridgeid',\n  'name',\n  'modelid',\n  'factorynew',\n  'replacesbridgeid',\n  'datastoreversion',\n  'starterkitid',\n  'zigbeechannel',\n  'apiversion',\n  'swversion',\n  'mac',\n  'ipaddress',\n  'dhcp',\n  'netmask',\n  'gateway',\n  'proxyaddress',\n  'proxyport',\n  'UTC',\n  'localtime',\n  'timezone',\n  'portalservices',\n  'portalconnection',\n  'linkbutton',\n  'touchlink',\n];\n\n/**\n * Bridge utils\n */\nclass Utils {\n  /**\n   * Validate bridge\n   *\n   * @param {mixed} bridge Bridge object\n   *\n   * @return {bool} True if valid\n   */\n  static validateBridge(bridge) {\n    if (bridge instanceof Bridge) {\n      return true;\n    }\n\n    throw new Error({\n      message: 'Expecting Bridge'\n    });\n  }\n\n  /**\n   * Build bridge\n   *\n   * @param {Object} result Result\n   *\n   * @return {Bridge} Bridge\n   */\n  static buildBridge(result) {\n    return new Bridge(\n      this.mapBridgeAttributes(result)\n    );\n  }\n\n  /**\n   * Map bridge attributes\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Attributes\n   */\n  static mapBridgeAttributes(result) {\n    let attributes = {};\n\n    if (result === undefined) {\n      return attributes;\n    }\n\n    for (let key of BRIDGE_ATTRIBUTES) {\n      if (key in result) {\n        attributes[key] = result[key];\n      }\n    }\n\n    return attributes;\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Command/Capability/GetGroups.js",
    "content": "'use strict';\n\nlet Groups = require('../../CapabilityModel/Groups');\n\n/**\n * Get groups command\n */\nclass GetGroups {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/capabilities`,\n      raw: true\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return new Groups(result.groups);\n      });\n  }\n}\n\nmodule.exports = GetGroups;\n"
  },
  {
    "path": "lib/Command/Capability/GetLights.js",
    "content": "'use strict';\n\nlet Lights = require('../../CapabilityModel/Lights');\n\n/**\n * Get lights command\n */\nclass GetLights {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/capabilities`,\n      raw: true\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return new Lights(result.lights);\n      });\n  }\n}\n\nmodule.exports = GetLights;\n"
  },
  {
    "path": "lib/Command/Capability/GetResourceLinks.js",
    "content": "'use strict';\n\nlet ResourceLinks = require('../../CapabilityModel/ResourceLinks');\n\n/**\n * Get resource links command\n */\nclass GetResourceLinks {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/capabilities`,\n      raw: true\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return new ResourceLinks(result.resourcelinks);\n      });\n  }\n}\n\nmodule.exports = GetResourceLinks;\n"
  },
  {
    "path": "lib/Command/Capability/GetRules.js",
    "content": "'use strict';\n\nlet Rules = require('../../CapabilityModel/Rules');\n\n/**\n * Get rules command\n */\nclass GetRules {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/capabilities`,\n      raw: true\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return new Rules(result.rules);\n      });\n  }\n}\n\nmodule.exports = GetRules;\n"
  },
  {
    "path": "lib/Command/Capability/GetScenes.js",
    "content": "'use strict';\n\nlet Scenes = require('../../CapabilityModel/Scenes');\n\n/**\n * Get scenes command\n */\nclass GetScenes {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/capabilities`,\n      raw: true\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return new Scenes(result.scenes);\n      });\n  }\n}\n\nmodule.exports = GetScenes;\n"
  },
  {
    "path": "lib/Command/Capability/GetSchedules.js",
    "content": "'use strict';\n\nlet Schedules = require('../../CapabilityModel/Schedules');\n\n/**\n * Get schedules command\n */\nclass GetSchedules {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/capabilities`,\n      raw: true\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return new Schedules(result.schedules);\n      });\n  }\n}\n\nmodule.exports = GetSchedules;\n"
  },
  {
    "path": "lib/Command/Capability/GetSensors.js",
    "content": "'use strict';\n\nlet Sensors = require('../../CapabilityModel/Sensors');\n\n/**\n * Get sensors command\n */\nclass GetSensors {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/capabilities`,\n      raw: true\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return new Sensors(result.sensors);\n      });\n  }\n}\n\nmodule.exports = GetSensors;\n"
  },
  {
    "path": "lib/Command/Capability/GetTimeZones.js",
    "content": "'use strict';\n\n/**\n * Get time zones command\n *\n * Get a list of supported time zones\n */\nclass GetTimeZones {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/capabilities`,\n      raw: true\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return result.timezones.values;\n      });\n  }\n}\n\nmodule.exports = GetTimeZones;\n"
  },
  {
    "path": "lib/Command/Group/CreateGroup.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'type',\n  'class',\n  'lights',\n];\n\n/**\n * Create group command\n *\n * Create a group\n */\nclass CreateGroup {\n  /**\n   * Constructor\n   *\n   * @param {Group} group Group\n   */\n  constructor(group) {\n    Utils.validateGroup(group);\n\n    this.group = group;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'POST',\n      url:    `api/${client.username}/groups`,\n      data:   {}\n    };\n\n    let attributes = this.group.attributes.getAll();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        this.group.attributes.resetChanged();\n\n        this.group.attributes.replace({\n          id: result.id\n        });\n\n        return this.group;\n      });\n  }\n}\n\nmodule.exports = CreateGroup;\n"
  },
  {
    "path": "lib/Command/Group/DeleteGroup.js",
    "content": "'use strict';\n\n/**\n * Delete group command\n *\n * Delete a group by id\n */\nclass DeleteGroup {\n  /**\n   * Constructor\n   *\n   * @param {string} groupId Group Id or Group object\n   */\n  constructor(groupId) {\n    this.groupId = String(groupId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'DELETE',\n      url:    `api/${client.username}/groups/${this.groupId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = DeleteGroup;\n"
  },
  {
    "path": "lib/Command/Group/GetGroup.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get group command\n *\n * Get a group by id\n */\nclass GetGroup {\n  /**\n   * Constructor\n   *\n   * @param {int} groupId Group Id\n   */\n  constructor(groupId) {\n    this.groupId = Number(groupId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/groups/${this.groupId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        result.id = this.groupId;\n\n        return Utils.buildGroup(result);\n      });\n  }\n}\n\nmodule.exports = GetGroup;\n"
  },
  {
    "path": "lib/Command/Group/GetGroups.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get groups command\n *\n * Get a list of groups\n */\nclass GetGroups {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/groups`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Object.keys(result).map(groupId => {\n          result[groupId].id = groupId;\n\n          return Utils.buildGroup(result[groupId]);\n        });\n      });\n  }\n}\n\nmodule.exports = GetGroups;\n"
  },
  {
    "path": "lib/Command/Group/SaveGroup.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'lights'\n];\n\n/**\n * Save group command\n *\n * Save a group\n */\nclass SaveGroup {\n  /**\n   * Constructor\n   *\n   * @param {Group} group Group\n   */\n  constructor(group) {\n    Utils.validateGroup(group);\n\n    this.group = group;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/groups/${this.group.id}`,\n      data:   {}\n    };\n\n    let attributes = this.group.attributes.getChanged();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => {\n        this.group.attributes.resetChanged();\n\n        return this.group;\n      });\n  }\n}\n\nmodule.exports = SaveGroup;\n"
  },
  {
    "path": "lib/Command/Group/SaveGroupAction.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ACTION = [\n  'on',\n  'bri',\n  'hue',\n  'sat',\n  'xy',\n  'ct',\n  'alert',\n  'effect',\n  'scene',\n  'transitiontime',\n  'bri_inc',\n  'hue_inc',\n  'sat_inc',\n  'xy_inc',\n  'ct_inc',\n];\n\n/**\n * Save group action command\n *\n * Saves group action\n */\nclass SaveGroupAction {\n  /**\n   * Constructor\n   *\n   * @param {Group} group Group\n   */\n  constructor(group) {\n    Utils.validateGroup(group);\n\n    this.group = group;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/groups/${this.group.id}/action`,\n      data:   {},\n      multi:  true\n    };\n\n    let attributes = this.group.action.getChanged();\n    for (let key of ALLOWED_ACTION) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(results => {\n        this.refreshGroupAction(results);\n\n        return this.group;\n      });\n  }\n\n  /**\n   * Refresh group action\n   *\n   * @param {Object} results Results\n   */\n  refreshGroupAction(results) {\n    this.group.action.resetChanged();\n\n    let newAction = {};\n\n    for (let i in results) {\n      let key = i.match(/\\/action\\/(\\w+)$/)[1];\n\n      newAction[key] = results[i];\n    }\n\n    this.group.action.replace(Utils.mapGroupAction(newAction));\n  }\n}\n\nmodule.exports = SaveGroupAction;\n"
  },
  {
    "path": "lib/Command/Group/Utils.js",
    "content": "'use strict';\n\nlet Error = require('../../Error');\nlet Group = require('../../Model/Group');\n\nconst GROUP_ATTRIBUTES = [\n  'id',\n  'name',\n  'type',\n  'class',\n  'lights',\n  'modelid',\n  'uniqueid'\n];\n\nconst GROUP_STATE = [\n  'any_on',\n  'all_on'\n];\n\nconst GROUP_ACTION_ATTRIBUTES = [\n  'on',\n  'bri',\n  'colormode',\n  'hue',\n  'sat',\n  'xy',\n  'ct',\n  'transitiontime',\n  'alert',\n  'effect',\n  'scene'\n];\n\n/**\n * Group utils\n */\nclass Utils {\n  /**\n   * Validate group\n   *\n   * @param {mixed} group Group object\n   *\n   * @return {bool} True if valid\n   */\n  static validateGroup(group) {\n    if (group instanceof Group) {\n      return true;\n    }\n\n    throw new Error({\n      message: 'Expecting Group'\n    });\n  }\n\n  /**\n   * Build group\n   *\n   * @param {Object} result Result\n   *\n   * @return {Group} Group\n   */\n  static buildGroup(result) {\n    return new Group(\n      this.mapGroupAttributes(result),\n      this.mapGroupState(result.state),\n      this.mapGroupAction(result.action)\n    );\n  }\n\n  /**\n   * Map group attributes\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Attributes\n   */\n  static mapGroupAttributes(result) {\n    let attributes = {};\n\n    if (result === undefined) {\n      return attributes;\n    }\n\n    for (let key of GROUP_ATTRIBUTES) {\n      if (key in result) {\n        attributes[key] = result[key];\n      }\n    }\n\n    return attributes;\n  }\n\n  /**\n   * Map group state\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} State\n   */\n  static mapGroupState(result) {\n    let state = {};\n\n    if (result === undefined) {\n      return state;\n    }\n\n    for (let key of GROUP_STATE) {\n      if (key in result) {\n        state[key] = result[key];\n      }\n    }\n\n    return state;\n  }\n\n  /**\n   * Map group action\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Action\n   */\n  static mapGroupAction(result) {\n    let action = {};\n\n    if (result === undefined) {\n      return action;\n    }\n\n    for (let key of GROUP_ACTION_ATTRIBUTES) {\n      if (key in result) {\n        action[key] = result[key];\n      }\n    }\n\n    return action;\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Command/InternetServices/GetInternetServices.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get internet services command\n *\n * Get internet services connectivity info\n */\nclass GetInternetServices {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/config`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Utils.buildInternetServices(result.internetservices);\n      });\n  }\n}\n\nmodule.exports = GetInternetServices;\n"
  },
  {
    "path": "lib/Command/InternetServices/Utils.js",
    "content": "'use strict';\n\nlet InternetServices = require('../../Model/InternetServices');\n\nconst INTERNET_SERVICES_ATTRIBUTES = [\n  'internet',\n  'remoteaccess',\n  'time',\n  'swupdate',\n];\n\n/**\n * Internet services utils\n */\nclass Utils {\n  /**\n   * Build internet services\n   *\n   * @param {Object} result Result\n   *\n   * @return {InternetServices} Internet services\n   */\n  static buildInternetServices(result) {\n    return new InternetServices(\n      this.mapInternetServicesAttributes(result)\n    );\n  }\n\n  /**\n   * Map internet services attributes\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Attributes\n   */\n  static mapInternetServicesAttributes(result) {\n    let attributes = {};\n\n    if (result === undefined) {\n      return attributes;\n    }\n\n    for (let key of INTERNET_SERVICES_ATTRIBUTES) {\n      if (key in result) {\n        attributes[key] = result[key];\n      }\n    }\n\n    return attributes;\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Command/Light/DeleteLight.js",
    "content": "'use strict';\n\n/**\n * Delete light command\n *\n * Delete a light by id\n */\nclass DeleteLight {\n  /**\n   * Constructor\n   *\n   * @param {string} lightId Light Id or Light object\n   */\n  constructor(lightId) {\n    this.lightId = String(lightId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'DELETE',\n      url:    `api/${client.username}/lights/${this.lightId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = DeleteLight;\n"
  },
  {
    "path": "lib/Command/Light/GetLight.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get light command\n *\n * Get a light by id\n */\nclass GetLight {\n  /**\n   * Constructor\n   *\n   * @param {int} lightId Light Id\n   */\n  constructor(lightId) {\n    this.lightId = Number(lightId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/lights/${this.lightId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        result.id = this.lightId;\n\n        return Utils.buildLight(result);\n      });\n  }\n}\n\nmodule.exports = GetLight;\n"
  },
  {
    "path": "lib/Command/Light/GetLights.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get lights command\n *\n * Get a list of lights\n */\nclass GetLights {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/lights`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Object.keys(result).map(lightId => {\n          result[lightId].id = lightId;\n\n          return Utils.buildLight(result[lightId]);\n        });\n      });\n  }\n}\n\nmodule.exports = GetLights;\n"
  },
  {
    "path": "lib/Command/Light/GetNewLights.js",
    "content": "'use strict';\n\nlet GetLights = require('./GetLights');\n\n/**\n * Get new lights command\n *\n * Get a list of new lights\n */\nclass GetNewLights {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/lights/new`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        delete result.lastscan;\n\n        let newLightIds = Object.keys(result);\n\n        return (new GetLights).invoke(client)\n          .then(lights => {\n            let newLights = [];\n\n            for (let light of lights) {\n              if (newLightIds.indexOf(light.id) > -1) {\n                newLights.push(light);\n              }\n            }\n\n            return newLights;\n          });\n      });\n  }\n}\n\nmodule.exports = GetNewLights;\n"
  },
  {
    "path": "lib/Command/Light/SaveLight.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name'\n];\n\n/**\n * Save light command\n *\n * Saves light\n */\nclass SaveLight {\n  /**\n   * Constructor\n   *\n   * @param {Light} light Light\n   */\n  constructor(light) {\n    Utils.validateLight(light);\n\n    this.light = light;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let promises = [];\n\n    let attributes = this.light.attributes.getChanged();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        promises.push(\n          this.saveLightAttribute(\n            client,\n            key,\n            attributes[key]\n          )\n        );\n      }\n    }\n\n    return Promise.all(promises)\n      .then(results => {\n        this.light.attributes.resetChanged();\n\n        return this.light;\n      });\n  }\n\n  /**\n   * Save light attribute\n   *\n   * @param {Client} client    Client\n   * @param {string} attribute Attribute\n   * @param {mixed}  value     Value\n   *\n   * @return {Promise} Promise for chaining\n   */\n  saveLightAttribute(client, attribute, value) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/lights/${this.light.id}`,\n      data:   {}\n    };\n\n    options.data[attribute] = value;\n\n    return client.getTransport()\n      .sendRequest(options);\n  }\n}\n\nmodule.exports = SaveLight;\n"
  },
  {
    "path": "lib/Command/Light/SaveLightState.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_STATE = [\n  'on',\n  'bri',\n  'hue',\n  'sat',\n  'xy',\n  'ct',\n  'alert',\n  'effect',\n  'transitiontime',\n  'bri_inc',\n  'hue_inc',\n  'sat_inc',\n  'xy_inc',\n  'ct_inc',\n];\n\n/**\n * Save light state command\n *\n * Saves light state\n */\nclass SaveLightState {\n  /**\n   * Constructor\n   *\n   * @param {Light} light Light\n   */\n  constructor(light) {\n    Utils.validateLight(light);\n\n    this.light = light;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/lights/${this.light.id}/state`,\n      data:   {},\n      multi:  true\n    };\n\n    let attributes = this.light.state.getChanged()\n    for (let key of ALLOWED_STATE) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(results => {\n        this.refreshLightState(results);\n\n        return this.light;\n      });\n  }\n\n  /**\n   * Refresh light state\n   *\n   * @param {Object} results Results\n   */\n  refreshLightState(results) {\n    this.light.state.resetChanged();\n\n    let newState = {};\n\n    for (let i in results) {\n      let key = i.match(/\\/state\\/(\\w+)$/)[1];\n\n      newState[key] = results[i];\n    }\n\n    this.light.state.replace(newState);\n  }\n}\n\nmodule.exports = SaveLightState;\n"
  },
  {
    "path": "lib/Command/Light/StartLightScan.js",
    "content": "'use strict';\n\n/**\n * Start light scan command\n *\n * Start a scan for new lights\n */\nclass StartLightScan {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'POST',\n      url:    `api/${client.username}/lights`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = StartLightScan;\n"
  },
  {
    "path": "lib/Command/Light/Utils.js",
    "content": "'use strict';\n\nlet Error = require('../../Error');\nlet Light = require('../../Model/Light');\n\nconst LIGHT_ATTRIBUTES = [\n  'id',\n  'name',\n  'type',\n  'uniqueid',\n  'manufacturername',\n  'modelid',\n  'productid',\n  'swversion',\n  'swconfigid'\n];\n\nconst LIGHT_STATE_ATTRIBUTES = [\n  'on',\n  'reachable',\n  'bri',\n  'colormode',\n  'hue',\n  'sat',\n  'xy',\n  'ct',\n  'transitiontime',\n  'alert',\n  'effect'\n];\n\n/**\n * Light utils\n */\nclass Utils {\n  /**\n   * Validate light\n   *\n   * @param {mixed} light Light object\n   *\n   * @return {bool} True if valid\n   */\n  static validateLight(light) {\n    if (light instanceof Light) {\n      return true;\n    }\n\n    throw new Error({\n      message: 'Expecting Light'\n    });\n  }\n\n  /**\n   * Build light\n   *\n   * @param {Object} result Result\n   *\n   * @return {Light} Light\n   */\n  static buildLight(result) {\n    return new Light(\n      this.mapLightAttributes(result),\n      this.mapLightState(result.state)\n    );\n  }\n\n  /**\n   * Map light attributes\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Attributes\n   */\n  static mapLightAttributes(result) {\n    let attributes = {};\n\n    if (result === undefined) {\n      return attributes;\n    }\n\n    for (let key of LIGHT_ATTRIBUTES) {\n      if (key in result) {\n        attributes[key] = result[key];\n      }\n    }\n\n    return attributes;\n  }\n\n  /**\n   * Map light state\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} State\n   */\n  static mapLightState(result) {\n    let state = {};\n\n    if (result === undefined) {\n      return state;\n    }\n\n    for (let key of LIGHT_STATE_ATTRIBUTES) {\n      if (key in result) {\n        state[key] = result[key];\n      }\n    }\n\n    return state;\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Command/Portal/GetPortal.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get portal command\n *\n * Get portal connectivity info\n */\nclass GetPortal {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/config`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Utils.buildPortal(result.portalstate);\n      });\n  }\n}\n\nmodule.exports = GetPortal;\n"
  },
  {
    "path": "lib/Command/Portal/Utils.js",
    "content": "'use strict';\n\nlet Portal = require('../../Model/Portal');\n\nconst PORTAL_ATTRIBUTES = [\n  'signedon',\n  'incoming',\n  'outgoing',\n  'communication',\n];\n\n/**\n * Portal utils\n */\nclass Utils {\n  /**\n   * Build portal\n   *\n   * @param {Object} result Result\n   *\n   * @return {Portal} Portal\n   */\n  static buildPortal(result) {\n    return new Portal(\n      this.mapPortalAttributes(result)\n    );\n  }\n\n  /**\n   * Map portal attributes\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Attributes\n   */\n  static mapPortalAttributes(result) {\n    let attributes = {};\n\n    if (result === undefined) {\n      return attributes;\n    }\n\n    for (let key of PORTAL_ATTRIBUTES) {\n      if (key in result) {\n        attributes[key] = result[key];\n      }\n    }\n\n    return attributes;\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Command/ResourceLinks/CreateResourceLink.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'description',\n  'classid',\n  'recycle',\n  'links'\n];\n\n/**\n * Create resource link command\n *\n * Create a resource link\n */\nclass CreateResourceLink {\n  /**\n   * Constructor\n   *\n   * @param {ResourceLink} resourceLink Resource Link\n   */\n  constructor(resourceLink) {\n    Utils.validateResourceLink(resourceLink);\n\n    this.resourceLink = resourceLink;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'POST',\n      url:    `api/${client.username}/resourcelinks`,\n      data:   {}\n    };\n\n    let attributes = this.resourceLink.attributes.getAll();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        this.resourceLink.attributes.resetChanged();\n\n        this.resourceLink.attributes.replace({\n          id: result.id\n        });\n\n        return this.resourceLink;\n      });\n  }\n}\n\nmodule.exports = CreateResourceLink;\n"
  },
  {
    "path": "lib/Command/ResourceLinks/DeleteResourceLink.js",
    "content": "'use strict';\n\n/**\n * Delete resource link command\n *\n * Delete a resource link by id\n */\nclass DeleteResourceLink {\n  /**\n   * Constructor\n   *\n   * @param {string} resourceLinkId Resource Link Id or ResourceLink object\n   */\n  constructor(resourceLinkId) {\n    this.resourceLinkId = String(resourceLinkId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'DELETE',\n      url:    `api/${client.username}/resourcelinks/${this.resourceLinkId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = DeleteResourceLink;\n"
  },
  {
    "path": "lib/Command/ResourceLinks/GetResourceLink.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get resource link command\n *\n * Get a resource link by id\n */\nclass GetResourceLink {\n  /**\n   * Constructor\n   *\n   * @param {int} resourceLinkId Resource link Id\n   */\n  constructor(resourceLinkId) {\n    this.resourceLinkId = Number(resourceLinkId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/resourcelinks/${this.resourceLinkId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        result.id = this.resourceLinkId;\n\n        return Utils.buildResourceLink(result);\n      });\n  }\n}\n\nmodule.exports = GetResourceLink;\n"
  },
  {
    "path": "lib/Command/ResourceLinks/GetResourceLinks.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get resource links command\n *\n * Get a list of resource links\n */\nclass GetResourceLinks {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/resourcelinks`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Object.keys(result).map(resourceLinkId => {\n          result[resourceLinkId].id = resourceLinkId;\n\n          return Utils.buildResourceLink(result[resourceLinkId]);\n        });\n      });\n  }\n}\n\nmodule.exports = GetResourceLinks;\n"
  },
  {
    "path": "lib/Command/ResourceLinks/SaveResourceLink.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'description',\n  'links'\n];\n\n/**\n * Save resource link command\n *\n * Save a resource link\n */\nclass SaveResourceLink {\n  /**\n   * Constructor\n   *\n   * @param {ResourceLink} resourceLink Resource Link\n   */\n  constructor(resourceLink) {\n    Utils.validateResourceLink(resourceLink);\n\n    this.resourceLink = resourceLink;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/resourcelinks/${this.resourceLink.id}`,\n      data:   {}\n    };\n\n    let attributes = this.resourceLink.attributes.getChanged();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => {\n        this.resourceLink.attributes.resetChanged();\n\n        return this.resourceLink;\n      });\n  }\n}\n\nmodule.exports = SaveResourceLink;\n"
  },
  {
    "path": "lib/Command/ResourceLinks/Utils.js",
    "content": "'use strict';\n\nlet Error        = require('../../Error');\nlet ResourceLink = require('../../Model/ResourceLink');\n\nconst RESOURCE_LINK_ATTRIBUTES = [\n  'id',\n  'name',\n  'description',\n  'type',\n  'classid',\n  'owner',\n  'recycle',\n  'links'\n];\n\n/**\n * Resource link utils\n */\nclass Utils {\n  /**\n   * Validate resource link\n   *\n   * @param {mixed} resourceLink ResourceLink object\n   *\n   * @return {bool} True if valid\n   */\n  static validateResourceLink(resourceLink) {\n    if (resourceLink instanceof ResourceLink) {\n      return true;\n    }\n\n    throw new Error({\n      message: 'Expecting Resource Link'\n    });\n  }\n\n  /**\n   * Build resource link\n   *\n   * @param {Object} result Result\n   *\n   * @return {ResourceLink} Resource link\n   */\n  static buildResourceLink(result) {\n    return new ResourceLink(\n      this.mapResourceLinkAttributes(result)\n    );\n  }\n\n  /**\n   * Map resource link attributes\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Attributes\n   */\n  static mapResourceLinkAttributes(result) {\n    let attributes = {};\n\n    if (result === undefined) {\n      return attributes;\n    }\n\n    for (let key of RESOURCE_LINK_ATTRIBUTES) {\n      if (key in result) {\n        attributes[key] = result[key];\n      }\n    }\n\n    return attributes;\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Command/Rule/CreateRule.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'status',\n  'conditions',\n  'actions',\n];\n\n/**\n * Create rule command\n *\n * Create a rule\n */\nclass CreateRule {\n  /**\n   * Constructor\n   *\n   * @param {Rule} rule Rule\n   */\n  constructor(rule) {\n    Utils.validateRule(rule);\n\n    this.rule = rule;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'POST',\n      url:    `api/${client.username}/rules`,\n      data:   {}\n    };\n\n    Utils.convertConditions(this.rule);\n    Utils.convertActions(this.rule);\n\n    let attributes = this.rule.attributes.getAll();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        this.rule.attributes.resetChanged();\n\n        this.rule.attributes.replace({\n          id: result.id\n        });\n\n        return this.rule;\n      });\n  }\n}\n\nmodule.exports = CreateRule;\n"
  },
  {
    "path": "lib/Command/Rule/DeleteRule.js",
    "content": "'use strict';\n\n/**\n * Delete rule command\n *\n * Delete a rule by id\n */\nclass DeleteRule {\n  /**\n   * Constructor\n   *\n   * @param {string} ruleId Rule Id or Rule object\n   */\n  constructor(ruleId) {\n    this.ruleId = String(ruleId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'DELETE',\n      url:    `api/${client.username}/rules/${this.ruleId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = DeleteRule;\n"
  },
  {
    "path": "lib/Command/Rule/GetRule.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get rule command\n *\n * Get a rule by id\n */\nclass GetRule {\n  /**\n   * Constructor\n   *\n   * @param {string} ruleId Rule Id\n   */\n  constructor(ruleId) {\n    this.ruleId = String(ruleId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/rules/${this.ruleId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        result.id = this.ruleId;\n\n        return Utils.buildRule(result);\n      });\n  }\n}\n\nmodule.exports = GetRule;\n"
  },
  {
    "path": "lib/Command/Rule/GetRules.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get rules command\n *\n * Get a list of rules\n */\nclass GetRules {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/rules`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Object.keys(result).map(ruleId => {\n          result[ruleId].id = ruleId;\n\n          return Utils.buildRule(result[ruleId]);\n        })\n      });\n  }\n}\n\nmodule.exports = GetRules;\n"
  },
  {
    "path": "lib/Command/Rule/SaveRule.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'status',\n  'conditions',\n  'actions',\n];\n\n/**\n * Save rule command\n *\n * Save a rule\n */\nclass SaveRule {\n  /**\n   * Constructor\n   *\n   * @param {Rule} rule Rule\n   */\n  constructor(rule) {\n    Utils.validateRule(rule);\n\n    this.rule = rule;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/rules/${this.rule.id}`,\n      data:   {}\n    };\n\n    Utils.convertConditions(this.rule);\n    Utils.convertActions(this.rule);\n\n    let attributes = this.rule.attributes.getChanged();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => {\n        this.rule.attributes.resetChanged();\n\n        return this.rule;\n      });\n  }\n}\n\nmodule.exports = SaveRule;\n"
  },
  {
    "path": "lib/Command/Rule/Utils.js",
    "content": "'use strict';\n\nlet AbstractAction = require('../../Action/AbstractAction');\nlet Condition      = require('../../Model/Condition');\nlet Error          = require('../../Error');\nlet Rule           = require('../../Model/Rule');\n\n/**\n * Rule utils\n */\nclass Utils {\n  /**\n   * Validate rule\n   *\n   * @param {mixed} rule Rule object\n   *\n   * @return {bool} True if valid\n   */\n  static validateRule(rule) {\n    if (rule instanceof Rule) {\n      return true;\n    }\n\n    throw new Error({\n      message: 'Expecting Rule'\n    });\n  }\n\n  /**\n   * Build rule\n   *\n   * @param {Object} result Result\n   *\n   * @return {Rule} Rule\n   */\n  static buildRule(result) {\n    return new Rule(result);\n  }\n\n  /**\n   * Convert conditions\n   *\n   * @param {Rule} rule Rule\n   */\n  static convertConditions(rule) {\n    rule.conditions = rule.conditions.map(condition => {\n      if (!(condition instanceof Condition)) {\n        return condition;\n      }\n\n      return {\n        'address':  `/sensors/${condition.sensor.id}/state/${condition.attribute}`,\n        'operator': condition.operator,\n        'value':    condition.value\n      };\n    });\n  }\n\n  /**\n   * Convert rule actions\n   *\n   * @param {Rule}   rule   Rule\n   * @param {Client} client Client\n   */\n  static convertActions(rule, client) {\n    rule.actions = rule.actions.map(action => {\n      if (!(action instanceof AbstractAction)) {\n        return action;\n      }\n\n      return action.exportAction(client);\n    });\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Command/Scene/CreateScene.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'lights',\n  'recycle',\n  'appdata',\n  'transitiontime',\n];\n\n/**\n * Create scene command\n *\n * Create a scene\n */\nclass CreateScene {\n  /**\n   * Constructor\n   *\n   * @param {Scene} scene Scene\n   */\n  constructor(scene) {\n    Utils.validateScene(scene);\n\n    this.scene = scene;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'POST',\n      url:    `api/${client.username}/scenes`,\n      data:   {}\n    };\n\n    let attributes = this.scene.attributes.getAll();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        this.scene.attributes.resetChanged();\n\n        this.scene.attributes.replace({\n          id: result.id\n        });\n\n        return this.reloadSceneAttributes(client);\n      });\n  }\n\n  /**\n   * Reload scene attributes\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  reloadSceneAttributes(client) {\n    return client.getTransport()\n      .sendRequest({\n        url: `api/${client.username}/scenes/${this.scene.id}`\n      })\n      .then(result => {\n        this.scene.attributes.replace(\n          Utils.mapSceneAttributes(result)\n        );\n\n        return this.scene;\n      });\n  }\n}\n\nmodule.exports = CreateScene;\n"
  },
  {
    "path": "lib/Command/Scene/DeleteScene.js",
    "content": "'use strict';\n\n/**\n * Delete scene command\n *\n * Delete a scene by id\n */\nclass DeleteScene {\n  /**\n   * Constructor\n   *\n   * @param {string} sceneId Scene Id or Scene object\n   */\n  constructor(sceneId) {\n    this.sceneId = String(sceneId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'DELETE',\n      url:    `api/${client.username}/scenes/${this.sceneId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = DeleteScene;\n"
  },
  {
    "path": "lib/Command/Scene/GetSceneById.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get scene by id command\n *\n * Get a list of scenes\n */\nclass GetSceneById {\n  /**\n   * Constructor\n   *\n   * @param {int} sceneId Scene Id\n   */\n  constructor(sceneId) {\n    this.sceneId = String(sceneId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/scenes/${this.sceneId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        result.id = this.sceneId;\n\n        return Utils.buildScene(result);\n      });\n  }\n}\n\nmodule.exports = GetSceneById;\n"
  },
  {
    "path": "lib/Command/Scene/GetScenes.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get scenes command\n *\n * Get a list of scenes\n */\nclass GetScenes {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/scenes`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Object.keys(result).map(sceneId => {\n          result[sceneId].id = sceneId;\n\n          return Utils.buildScene(result[sceneId]);\n        })\n      });\n  }\n}\n\nmodule.exports = GetScenes;\n"
  },
  {
    "path": "lib/Command/Scene/RecallScene.js",
    "content": "'use strict';\n\n/**\n * Recall scene command\n *\n * Recall a scene\n */\nclass RecallScene {\n  /**\n   * Constructor\n   *\n   * @param {string} sceneId Scene Id\n   */\n  constructor(sceneId) {\n    this.sceneId = String(sceneId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/groups/0/action`,\n      data:   {\n        scene: this.sceneId\n      }\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n\n}\n\nmodule.exports = RecallScene;\n"
  },
  {
    "path": "lib/Command/Scene/SaveScene.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'lights',\n  'recycle',\n  'appdata',\n  'storelightstate',\n  'transitiontime',\n];\n\n/**\n * Save scene command\n *\n * Save a scene\n */\nclass SaveScene {\n  /**\n   * Constructor\n   *\n   * @param {Scene} scene Scene\n   */\n  constructor(scene) {\n    Utils.validateScene(scene);\n\n    this.scene = scene;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/scenes/${this.scene.id}`,\n      data:   {}\n    };\n\n    let attributes = this.scene.attributes.getChanged();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => {\n        this.scene.attributes.resetChanged();\n\n        return this.reloadSceneAttributes(client);\n      });\n  }\n\n  /**\n   * Reload scene attributes\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  reloadSceneAttributes(client) {\n    return client.getTransport()\n      .sendRequest({\n        url: `api/${client.username}/scenes/${this.scene.id}`\n      })\n      .then(result => {\n        this.scene.attributes.replace(\n          Utils.mapSceneAttributes(result)\n        );\n\n        return this.scene;\n      });\n  }\n}\n\nmodule.exports = SaveScene;\n"
  },
  {
    "path": "lib/Command/Scene/SaveSceneLightState.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst STATE_MAP = {\n  'on':             'on',\n  'brightness':     'bri',\n  'hue':            'hue',\n  'saturation':     'sat',\n  'xy':             'xy',\n  'colorTemp':      'ct',\n  'effect':         'effect',\n  'transitionTime': 'transitiontime',\n};\n\n/**\n * Save scene light state command\n *\n * Saves scene light state\n */\nclass SaveSceneLightState {\n  /**\n   * Save scene light state\n   *\n   * @param {Scene} scene Scene object\n   */\n  constructor(scene) {\n    Utils.validateScene(scene);\n\n    this.scene = scene;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let lightStates = this.scene.lightStates.getChanged();\n    this.scene.lightStates.resetChanged();\n\n    let promises = [];\n\n    for (let key in lightStates) {\n      promises.push(\n        this.saveLightState(client, key, lightStates[key])\n      );\n    }\n\n    return Promise.all(promises)\n      .then(() => this.scene);\n  }\n\n  /**\n   * Save light state\n   *\n   * @param {Client} client  Client\n   * @param {string} lightId Light id\n   * @param {Object} state   Light state\n   *\n   * @return {Promise} Promise for chaining\n   */\n  saveLightState(client, lightId, state) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/scenes/${this.scene.id}/lightstates/${lightId}`,\n      data:   {}\n    };\n\n    for (let key in state) {\n      if (key in STATE_MAP) {\n        options.data[STATE_MAP[key]] = state[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = SaveSceneLightState;\n"
  },
  {
    "path": "lib/Command/Scene/Utils.js",
    "content": "'use strict';\n\nlet Error = require('../../Error');\nlet Light = require('../../Model/Light');\nlet Scene = require('../../Model/Scene');\n\nconst SCENE_ATTRIBUTES = [\n  'id',\n  'lights',\n  'name',\n  'owner',\n  'recycle',\n  'locked',\n  'appdata',\n  'picture',\n  'lastupdated',\n  'version',\n  'transitiontime',\n  'storelightstate',\n];\n\n/**\n * Scene utils\n */\nclass Utils {\n  /**\n   * Validate scene\n   *\n   * @param {mixed} scene Scene object\n   *\n   * @return {bool} True if valid\n   */\n  static validateScene(scene) {\n    if (scene instanceof Scene) {\n      return true;\n    }\n\n    throw new Error({\n      message: 'Expecting Scene'\n    });\n  }\n\n  /**\n   * Build scene\n   *\n   * @param {Object} result Result\n   *\n   * @return {Scene} Scene\n   */\n  static buildScene(result) {\n    return new Scene(\n      this.mapSceneAttributes(result),\n      this.mapSceneLightStates(result)\n    );\n  }\n\n  /**\n   * Map scene attributes\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Attributes\n   */\n  static mapSceneAttributes(result) {\n    let attributes = {};\n\n    if (result === undefined) {\n      return attributes;\n    }\n\n    for (let key of SCENE_ATTRIBUTES) {\n      if (key in result) {\n        attributes[key] = result[key];\n      }\n    }\n\n    return attributes;\n  }\n\n  /**\n   * Map scene light states\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Light states\n   */\n  static mapSceneLightStates(result) {\n    let lightStates = {};\n\n    if (result.lightstates !== undefined) {\n      return Object.assign({}, result.lightstates);\n    }\n\n    return {};\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Command/Schedule/CreateSchedule.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'description',\n  'command',\n  'localtime',\n  'status',\n  'autodelete'\n];\n\n/**\n * Create schedule command\n *\n * Create a schedule\n */\nclass CreateSchedule {\n  /**\n   * Constructor\n   *\n   * @param {Schedule} schedule Schedule\n   */\n  constructor(schedule) {\n    Utils.validateSchedule(schedule);\n\n    this.schedule = schedule;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'POST',\n      url:    `api/${client.username}/schedules`,\n      data:   {}\n    };\n\n    Utils.convertAction(this.schedule, client);\n\n    let attributes = this.schedule.attributes.getAll();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        this.schedule.attributes.resetChanged();\n\n        this.schedule.attributes.replace({\n          id: result.id\n        });\n\n        return this.schedule;\n      });\n  }\n}\n\nmodule.exports = CreateSchedule;\n"
  },
  {
    "path": "lib/Command/Schedule/DeleteSchedule.js",
    "content": "'use strict';\n\n/**\n * Delete schedule command\n *\n * Delete a schedule by id\n */\nclass DeleteSchedule {\n  /**\n   * Constructor\n   *\n   * @param {string} scheduleId Schedule Id or Schedule object\n   */\n  constructor(scheduleId) {\n    this.scheduleId = String(scheduleId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'DELETE',\n      url:    `api/${client.username}/schedules/${this.scheduleId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = DeleteSchedule;\n"
  },
  {
    "path": "lib/Command/Schedule/GetSchedule.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get schedule command\n *\n * Get a schedule by id\n */\nclass GetSchedule {\n  /**\n   * Constructor\n   *\n   * @param {int} scheduleId Schedule Id\n   */\n  constructor(scheduleId) {\n    this.scheduleId = Number(scheduleId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/schedules/${this.scheduleId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        result.id = this.scheduleId;\n\n        return Utils.buildSchedule(result);\n      });\n  }\n}\n\nmodule.exports = GetSchedule;\n"
  },
  {
    "path": "lib/Command/Schedule/GetSchedules.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get schedules command\n *\n * Get a list of schedules\n */\nclass GetSchedules {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/schedules`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Object.keys(result).map(scheduleId => {\n          result[scheduleId].id = scheduleId;\n\n          return Utils.buildSchedule(result[scheduleId]);\n        })\n      });\n  }\n}\n\nmodule.exports = GetSchedules;\n"
  },
  {
    "path": "lib/Command/Schedule/SaveSchedule.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'description',\n  'command',\n  'localtime',\n  'status',\n  'autodelete'\n];\n\n/**\n * Save schedule command\n *\n * Save a schedule\n */\nclass SaveSchedule {\n  /**\n   * Constructor\n   *\n   * @param {Schedule} schedule Schedule\n   */\n  constructor(schedule) {\n    Utils.validateSchedule(schedule);\n\n    this.schedule = schedule;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/schedules/${this.schedule.id}`,\n      data:   {}\n    };\n\n    Utils.convertAction(this.schedule, client);\n\n    let attributes = this.schedule.attributes.getChanged();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        this.schedule.attributes.resetChanged();\n\n        return this.schedule;\n      });\n  }\n}\n\nmodule.exports = SaveSchedule;\n"
  },
  {
    "path": "lib/Command/Schedule/Utils.js",
    "content": "'use strict';\n\nlet Error          = require('../../Error');\nlet AbstractAction = require('../../Action/AbstractAction');\nlet Schedule       = require('../../Model/Schedule');\n\nconst SCHEDULE_ATTRIBUTES = [\n  'id',\n  'name',\n  'description',\n  'command',\n  'localtime',\n  'created',\n  'status',\n  'autodelete',\n  'starttime'\n];\n\n/**\n * Schedule utils\n */\nclass Utils {\n  /**\n   * Validate schedule\n   *\n   * @param {mixed} schedule Schedule object\n   *\n   * @return {bool} True if valid\n   */\n  static validateSchedule(schedule) {\n    if (schedule instanceof Schedule) {\n      return true;\n    }\n\n    throw new Error({\n      message: 'Expecting Schedule'\n    });\n  }\n\n  /**\n   * Build schedule\n   *\n   * @param {Object} result Result\n   *\n   * @return {Schedule} Schedule\n   */\n  static buildSchedule(result) {\n    return new Schedule(\n      this.mapScheduleAttributes(result)\n    );\n  }\n\n  /**\n   * Map schedule attributes\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Attributes\n   */\n  static mapScheduleAttributes(result) {\n    let attributes = {};\n\n    if (result === undefined) {\n      return attributes;\n    }\n\n    for (let key of SCHEDULE_ATTRIBUTES) {\n      if (key in result) {\n        attributes[key] = result[key];\n      }\n    }\n\n    return attributes;\n  }\n\n  /**\n   * Convert schedule action\n   *\n   * @param {Schedule} schedule Schedule\n   * @param {Client}   client   Client\n   */\n  static convertAction(schedule, client) {\n    let action = schedule.attributes.get('command');\n\n    if (!(action instanceof AbstractAction)) {\n      return;\n    }\n\n    schedule.attributes.set('command', action.exportAction(client, true));\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Command/Sensor/CreateSensor.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name',\n  'type',\n  'modelid',\n  'manufacturername',\n  'swversion',\n  'uniqueid',\n];\n\n/**\n * Create sensor command\n *\n * Create a sensor\n */\nclass CreateSensor {\n  /**\n   * Constructor\n   *\n   * @param {Sensor} sensor Sensor\n   */\n  constructor(sensor) {\n    Utils.validateSensor(sensor);\n\n    this.sensor = sensor;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'POST',\n      url:    `api/${client.username}/sensors`,\n      data:   {\n        config: this.sensor.config.attributes.getAll(),\n        state:  this.sensor.state.attributes.getAll()\n      }\n    };\n\n    let attributes = this.sensor.attributes.getAll();\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        options.data[key] = attributes[key];\n      }\n    }\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        this.sensor.attributes.resetChanged();\n\n        this.sensor.attributes.replace({\n          id: result.id\n        });\n\n        return this.sensor;\n      });\n  }\n}\n\nmodule.exports = CreateSensor;\n"
  },
  {
    "path": "lib/Command/Sensor/DeleteSensor.js",
    "content": "'use strict';\n\n/**\n * Delete sensor command\n *\n * Delete a sensor by id\n */\nclass DeleteSensor {\n  /**\n   * Constructor\n   *\n   * @param {string} sensorId Sensor Id or Sensor object\n   */\n  constructor(sensorId) {\n    this.sensorId = String(sensorId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'DELETE',\n      url:    `api/${client.username}/sensors/${this.sensorId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = DeleteSensor;\n"
  },
  {
    "path": "lib/Command/Sensor/GetNewSensors.js",
    "content": "'use strict';\n\nlet GetSensors = require('./GetSensors');\n\n/**\n * Get new sensors command\n *\n * Get a list of new sensors\n */\nclass GetNewSensors {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/sensors/new`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        delete result.lastscan;\n\n        let newSensorIds = Object.keys(result);\n\n        return client.invokeCommand(new GetSensors)\n          .then(sensors => {\n            let newSensors = [];\n\n            for (let sensor of sensors) {\n              if (newSensorIds.indexOf(sensor.id) > -1) {\n                newSensors.push(sensor);\n              }\n            }\n\n            return newSensors;\n          });\n      });\n  }\n}\n\nmodule.exports = GetNewSensors;\n"
  },
  {
    "path": "lib/Command/Sensor/GetSensor.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get sensor command\n *\n * Get a sensor by id\n */\nclass GetSensor {\n  /**\n   * Constructor\n   *\n   * @param {int} sensorId Sensor Id\n   */\n  constructor(sensorId) {\n    this.sensorId = Number(sensorId);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/sensors/${this.sensorId}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        result.id = this.sensorId;\n\n        return Utils.buildSensor(result);\n      });\n  }\n}\n\nmodule.exports = GetSensor;\n"
  },
  {
    "path": "lib/Command/Sensor/GetSensors.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get sensors command\n *\n * Get a list of sensors\n */\nclass GetSensors {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/sensors`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Object.keys(result).map(sensorId => {\n          result[sensorId].id = sensorId;\n\n          return Utils.buildSensor(result[sensorId]);\n        })\n      });\n  }\n}\n\nmodule.exports = GetSensors;\n"
  },
  {
    "path": "lib/Command/Sensor/SaveSensor.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\nconst ALLOWED_ATTRIBUTES = [\n  'name'\n];\n\n/**\n * Save sensor command\n *\n * Saves sensor\n */\nclass SaveSensor {\n  /**\n   * Constructor\n   *\n   * @param {Sensor} sensor Sensor\n   */\n  constructor(sensor) {\n    Utils.validateSensor(sensor);\n\n    this.sensor = sensor;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let attributes = this.sensor.attributes.getChanged();\n    let promises   = [];\n\n    for (let key of ALLOWED_ATTRIBUTES) {\n      if (key in attributes) {\n        promises.push(\n          client,\n          key,\n          attributes[key]\n        );\n      }\n    }\n\n    return Promise.all(promises)\n      .then(() => {\n        return this.sensor;\n      });\n  }\n\n  /**\n   * Save sensor attribute\n   *\n   * @param {Client} client    Client\n   * @param {string} attribute Attribute\n   * @param {mixed}  value     Value\n   *\n   * @return {Promise} Promise for chaining\n   */\n  saveSensorAttribute(client, attribute, value) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/sensors/${this.sensor.id}`,\n      data:   {}\n    };\n\n    options.data[attribute] = value;\n\n    return client.getTransport()\n      .sendRequest(options);\n  }\n}\n\nmodule.exports = SaveSensor;\n"
  },
  {
    "path": "lib/Command/Sensor/SaveSensorConfig.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Save sensor config command\n *\n * Saves sensor config\n */\nclass SaveSensorConfig {\n  /**\n   * Constructor\n   *\n   * @param {Sensor} sensor Sensor\n   */\n  constructor(sensor) {\n    Utils.validateSensor(sensor);\n\n    this.sensor = sensor;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/sensors/${this.sensor.id}/config`,\n      data:   this.sensor.config.attributes.getChanged()\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => {\n        this.sensor.config.attributes.resetChanged();\n\n        return this.sensor;\n      });\n  }\n}\n\nmodule.exports = SaveSensorConfig;\n"
  },
  {
    "path": "lib/Command/Sensor/SaveSensorState.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Save sensor state command\n *\n * Saves sensor state\n */\nclass SaveSensorState {\n  /**\n   * Constructor\n   *\n   * @param {Sensor} sensor Sensor\n   */\n  constructor(sensor) {\n    Utils.validateSensor(sensor);\n\n    this.sensor = sensor;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/sensors/${this.sensor.id}/state`,\n      data:   this.sensor.state.attributes.getChanged()\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => {\n        this.sensor.state.attributes.resetChanged();\n\n        return this.sensor;\n      });\n  }\n}\n\nmodule.exports = SaveSensorState;\n"
  },
  {
    "path": "lib/Command/Sensor/StartSensorScan.js",
    "content": "'use strict';\n\n/**\n * Start sensor scan command\n *\n * Start a scan for new sensors\n */\nclass StartSensorScan {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'POST',\n      url:    `api/${client.username}/sensors`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = StartSensorScan;\n"
  },
  {
    "path": "lib/Command/Sensor/Utils.js",
    "content": "'use strict';\n\nlet Error  = require('../../Error');\nlet Sensor = require('../../Model/Sensor');\n\nconst SENSOR_ATTRIBUTES = [\n  'id',\n  'name',\n  'type',\n  'modelid',\n  'manufacturername',\n  'productid',\n  'swversion',\n  'swconfigid',\n  'uniqueid',\n];\n\n/**\n * Sensor utils\n */\nclass Utils {\n  /**\n   * Validate sensor\n   *\n   * @param {mixed} sensor Sensor object\n   *\n   * @return {bool} True if valid\n   */\n  static validateSensor(sensor) {\n    if (sensor instanceof Sensor) {\n      return true;\n    }\n\n    throw new Error({\n      message: 'Expecting Sensor'\n    });\n  }\n\n  /**\n   * Build sensor\n   *\n   * @param {Object} result Result\n   *\n   * @return {Sensor} Sensor\n   */\n  static buildSensor(result) {\n    return new Sensor(\n      this.mapSensorAttributes(result),\n      this.mapSensorConfig(result.config),\n      this.mapSensorState(result.state)\n    );\n  }\n\n  /**\n   * Map sensor attributes\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Attributes\n   */\n  static mapSensorAttributes(result) {\n    let attributes = {};\n\n    if (result === undefined) {\n      return attributes;\n    }\n\n    for (let key of SENSOR_ATTRIBUTES) {\n      if (key in result) {\n        attributes[key] = result[key];\n      }\n    }\n\n    return attributes;\n  }\n\n  /**\n   * Map sensor config\n   *\n   * @param {Object} config Config\n   *\n   * @return {Object} Config\n   */\n  static mapSensorConfig(config) {\n    return Object.assign({}, config);\n  }\n\n  /**\n   * Map sensor state\n   *\n   * @param {Object} state State\n   *\n   * @return {Object} State\n   */\n  static mapSensorState(state) {\n    return Object.assign({}, state);\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Command/SoftwareUpdate/CheckForSoftwareUpdates.js",
    "content": "'use strict';\n\n/**\n * Check for software updates command\n *\n * Updates bridge to check for software update\n */\nclass CheckForSoftwareUpdates {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/config`,\n      data:   {\n        'swupdate': {\n          'checkforupdate': true\n        }\n      }\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = CheckForSoftwareUpdates;\n"
  },
  {
    "path": "lib/Command/SoftwareUpdate/DisableInstallNotification.js",
    "content": "'use strict';\n\n/**\n * Disable install notification command\n *\n * Updates bridge to disable install notification\n */\nclass DisableInstallNotification {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url:    `api/${client.username}/config`,\n      data:   {\n        'swupdate': {\n          'notify': false\n        }\n      }\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = DisableInstallNotification;\n"
  },
  {
    "path": "lib/Command/SoftwareUpdate/GetSoftwareUpdate.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get software update command\n *\n * Get software update info\n */\nclass GetSoftwareUpdate {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/config`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Utils.buildSoftwareUpdate(result.swupdate);\n      });\n  }\n}\n\nmodule.exports = GetSoftwareUpdate;\n"
  },
  {
    "path": "lib/Command/SoftwareUpdate/InstallSoftwareUpdates.js",
    "content": "'use strict';\n\n/**\n * Install software updates command\n *\n * Updates bridge to install software updates\n */\nclass InstallSoftwareUpdates {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'PUT',\n      url :   `api/${client.username}/config`,\n      data:   {\n        'swupdate': {\n          'updatestate': 3\n        }\n      }\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = InstallSoftwareUpdates;\n"
  },
  {
    "path": "lib/Command/SoftwareUpdate/Utils.js",
    "content": "'use strict';\n\nlet SoftwareUpdate = require('../../Model/SoftwareUpdate');\n\nconst SW_ATTRIBUTES = [\n  'updatestate',\n  'checkforupdate',\n  'devicetypes',\n  'url',\n  'text',\n  'notify'\n];\n\n/**\n * Software update utils\n */\nclass Utils {\n  /**\n   * Build software update\n   *\n   * @param {Object} result Result\n   *\n   * @return {SoftwareUpdate} Software update\n   */\n  static buildSoftwareUpdate(result) {\n    return new SoftwareUpdate(\n      this.mapSoftwareUpdateAttributes(result)\n    );\n  }\n\n  /**\n   * Map software update attributes\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Attributes\n   */\n  static mapSoftwareUpdateAttributes(result) {\n    let attributes = {};\n\n    if (result === undefined) {\n      return attributes;\n    }\n\n    for (let key of SW_ATTRIBUTES) {\n      if (key in result) {\n        attributes[key] = result[key];\n      }\n    }\n\n    return attributes;\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Command/TimeZone/GetTimeZones.js",
    "content": "'use strict';\n\nlet GetTimeZones = require('../Capability/GetTimeZones');\n\nmodule.exports = GetTimeZones;\n"
  },
  {
    "path": "lib/Command/User/CreateUser.js",
    "content": "'use strict';\n\nlet GetUser = require('./GetUser');\nlet Utils   = require('./Utils');\n\n/**\n * Create user command\n *\n * Create a user\n */\nclass CreateUser {\n  /**\n   * Constructor\n   *\n   * @param {User} user User\n   */\n  constructor(user) {\n    Utils.validateUser(user);\n\n    this.user = user;\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'POST',\n      url:    'api',\n      data: {\n        'devicetype': this.user.deviceType\n      }\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        this.user.attributes.set('username', result.username);\n\n        return this.user;\n      });\n  }\n}\n\nmodule.exports = CreateUser;\n"
  },
  {
    "path": "lib/Command/User/DeleteUser.js",
    "content": "'use strict';\n\n/**\n * Delete user command\n *\n * Delete a user by username\n */\nclass DeleteUser {\n  /**\n   * Constructor\n   *\n   * @param {string} username Username\n   */\n  constructor(username) {\n    this.username = String(username);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      method: 'DELETE',\n      url:    `api/${client.username}/config/whitelist/${this.username}`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(() => true);\n  }\n}\n\nmodule.exports = DeleteUser;\n"
  },
  {
    "path": "lib/Command/User/GetUser.js",
    "content": "'use strict';\n\nlet Error = require('../../Error');\nlet Utils = require('./Utils');\n\n/**\n * Get user command\n *\n * Get a user by username\n */\nclass GetUser {\n  /**\n   * Constructor\n   *\n   * @param {string} username Username\n   */\n  constructor(username) {\n    this.username = String(username);\n  }\n\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/config`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        if (!(this.username in result.whitelist)) {\n          throw new Error({\n            message: `User ${this.username} is not valid`\n          });\n        }\n\n        let userResult = result.whitelist[this.username];\n        userResult.username = this.username;\n\n        return Utils.buildUser(userResult);\n      });\n  }\n}\n\nmodule.exports = GetUser;\n"
  },
  {
    "path": "lib/Command/User/GetUsers.js",
    "content": "'use strict';\n\nlet Utils = require('./Utils');\n\n/**\n * Get users command\n *\n * Get a list of registered users\n */\nclass GetUsers {\n  /**\n   * Invoke command\n   *\n   * @param {Client} client Client\n   *\n   * @return {Promise} Promise for chaining\n   */\n  invoke(client) {\n    let options = {\n      url: `api/${client.username}/config`\n    };\n\n    return client.getTransport()\n      .sendRequest(options)\n      .then(result => {\n        return Object.keys(result.whitelist).map(username => {\n          let userResult = result.whitelist[username];\n          userResult.username = username;\n\n          return Utils.buildUser(userResult);\n        })\n      });\n  }\n}\n\nmodule.exports = GetUsers;\n"
  },
  {
    "path": "lib/Command/User/Utils.js",
    "content": "'use strict';\n\nlet Error = require('../../Error');\nlet User  = require('../../Model/User');\n\nconst USER_ATTRIBUTES = [\n  'username',\n  'name',\n  'create date',\n  'last use date',\n];\n\n/**\n * User utils\n */\nclass Utils {\n  /**\n   * Validate user\n   *\n   * @param {mixed} user User object\n   *\n   * @return {bool} True if valid\n   */\n  static validateUser(user) {\n    if (user instanceof User) {\n      return true;\n    }\n\n    throw new Error({\n      message: 'Expecting User'\n    });\n  }\n\n  /**\n   * Build user\n   *\n   * @param {Object} result Result\n   *\n   * @return {User} User\n   */\n  static buildUser(result) {\n    return new User(\n      this.mapUserAttributes(result)\n    );\n  }\n\n  /**\n   * Map user attributes\n   *\n   * @param {Object} result Result\n   *\n   * @return {Object} Attributes\n   */\n  static mapUserAttributes(result) {\n    let attributes = {};\n\n    if (result === undefined) {\n      return attributes;\n    }\n\n    for (let key of USER_ATTRIBUTES) {\n      if (key in result) {\n        attributes[key] = result[key];\n      }\n    }\n\n    return attributes;\n  }\n}\n\nmodule.exports = Utils;\n"
  },
  {
    "path": "lib/Discovery.js",
    "content": "'use strict';\n\nlet Error = require('./Error');\n\nconst ENABLED_STRATEGIES = {\n  nupnp: 'Nupnp',\n  upnp:  'Upnp',\n};\n\nconst DEFAULT_OPTIONS = {\n  strategy: 'all'\n};\n\n/**\n * Discovery\n *\n * Assists in finding bridges on local network\n */\nclass Discovery {\n  /**\n   * Constructor\n   *\n   * @param {object} options Options\n   */\n  constructor(options) {\n    this.options = Object.assign({}, DEFAULT_OPTIONS, options);\n  }\n\n  /**\n   * Convenience method for discovering bridges\n   *\n   * @param {object} options Options\n   *\n   * @return {Promise} Promise for chaining\n   */\n  static discoverBridges(options) {\n    return (new Discovery(options)).discover();\n  }\n\n  /**\n   * Invokes bridge discovery\n   *\n   * @return {Promise} Promise for chaining\n   */\n  discover() {\n    let strategies = [];\n\n    let selectedStrategies = (this.options['strategy'] === 'all')\n      ? Object.keys(ENABLED_STRATEGIES)\n      : [this.options['strategy']];\n\n    for (let strategy of selectedStrategies) {\n      strategies.push(getDiscoveryStrategy(strategy));\n    }\n\n    return Promise.all(strategies.map(strategy => strategy.discover()))\n      .then(results => {\n        let bridges = [];\n\n        results.map(results => {\n          results.map(bridge => {\n            bridges[bridge.id] = bridge;\n          });\n        });\n\n        return Object.keys(bridges).map(key => bridges[key]);\n      });\n  }\n}\n\n/**\n * Validate discovery strategy\n *\n * @param {string} strategy Strategy\n */\nfunction validateDiscoveryStrategy(strategy) {\n  if (!(strategy in ENABLED_STRATEGIES)) {\n    throw new Error({\n      message: `Discovery strategy ${strategy} not valid`\n    });\n  }\n}\n\n/**\n * Get discovery strategy\n *\n * @param {string} strategy Strategy\n *\n * @return {mixed} Discovery strategy\n */\nfunction getDiscoveryStrategy(strategy) {\n  validateDiscoveryStrategy(strategy);\n\n  let strategyClass = ENABLED_STRATEGIES[strategy];\n\n  return new (require(`./DiscoveryStrategy/${strategyClass}`));\n}\n\nmodule.exports = Discovery;\n"
  },
  {
    "path": "lib/DiscoveryStrategy/Nupnp.js",
    "content": "'use strict';\n\nlet axios = require('axios');\nlet Error = require('../Error');\n\nconst PHILIPS_NUPNP_URL = 'https://discovery.meethue.com/';\n\n/**\n * Nupnp discovery strategy\n *\n * Use meethue's endpoint for looking up local bridges\n */\nclass Nupnp {\n  /**\n   * Discover bridges\n   *\n   * @return {Promise} Promise for chaining\n   */\n  discover() {\n    return this.requestService();\n  }\n\n  /**\n   * Request service\n   *\n   * @return {Promise} Promise for chaining\n   */\n  requestService() {\n    let httpRequest = axios.get(PHILIPS_NUPNP_URL, {\n      responseType: 'json'\n    });\n\n    return httpRequest\n      .then(response => {\n        return response.data.map(bridge => {\n          return {\n            id: bridge.id.toUpperCase(),\n            ip: bridge.internalipaddress,\n          };\n        });\n      })\n      .catch(response => {\n        throw new Error({\n          message: 'Failed to get results from meethue'\n        });\n      });\n  }\n}\n\nmodule.exports = Nupnp;\n"
  },
  {
    "path": "lib/DiscoveryStrategy/Upnp.js",
    "content": "'use strict';\n\nlet dgram = require('dgram');\n\nconst SSDP_ADDRESS       = '239.255.255.250';\nconst SSDP_PORT          = 1900;\nconst SSDP_SEARCH_TARGET = 'upnp:rootdevice';\nconst SOURCE_INTERFACE   = '0.0.0.0';\nconst SOURCE_PORT        = 0;\nconst TIMEOUT_MS         = 3000;\n\n/**\n * Upnp discovery strategy\n *\n * Use UPnP on the local network for bridge discovery\n */\nclass Upnp {\n  /**\n   * Constructor\n   */\n  constructor() {\n    this.bridges = [];\n  }\n\n  /**\n   * Discover bridges\n   *\n   * @return {Promise} Promise for chaining\n   */\n  discover() {\n    return new Promise((resolve, reject) => {\n      this.startDiscovery(resolve, reject);\n    });\n  }\n\n  /**\n   * Start listener and broadcast UPnP search\n   *\n   * @param {function} resolve Promise resolve\n   * @param {function} reject  Promise reject\n   */\n  startDiscovery(resolve, reject) {\n    this.socket = dgram.createSocket('udp4');\n\n    this.socket.on('listening', () => {\n      this.broadcast();\n    });\n\n    this.socket.on('message', (message, remote) => {\n      this.handleMessage(message);\n    });\n\n    this.socket.bind(SOURCE_PORT, SOURCE_INTERFACE);\n\n    setTimeout(() => this.stopDiscovery(resolve, reject), TIMEOUT_MS);\n  }\n\n  /**\n   * Use SSDP discovery broadcast\n   */\n  broadcast() {\n    let query = Buffer.from(\n      [\n        'M-SEARCH * HTTP/1.1',\n        `HOST: ${SSDP_ADDRESS}:${SSDP_PORT}`,\n        'MAN: \"sddp:discover\"',\n        'MX: 3',\n        `ST: ${SSDP_SEARCH_TARGET}`,\n        ''\n      ].join('\\r\\n')\n    );\n\n    this.socket.send(query, 0, query.length, SSDP_PORT, SSDP_ADDRESS);\n  }\n\n  /**\n   * Handle incoming message\n   *\n   * @param {mixed} message Message received\n   */\n  handleMessage(message) {\n    var message = message.toString();\n\n    let match = message.match(/hue-bridgeid: (.*?)\\r\\n/i);\n    if (!match || !(1 in match)) {\n      return;\n    }\n\n    let bridgeId = match[1];\n    let bridgeIp = message.match(/LOCATION: https?:\\/\\/([\\.0-9]+).*?\\r\\n/i)[1];\n\n    this.bridges[bridgeId] = {\n      id: bridgeId,\n      ip: bridgeIp\n    };\n  }\n\n  /**\n   * Stop discovery\n   *\n   * @param {function} resolve Promise resolve\n   * @param {function} reject  Promise reject\n   */\n  stopDiscovery(resolve, reject) {\n    this.socket.close(\n      () => resolve(\n        Object.keys(this.bridges).map(key => this.bridges[key])\n      )\n    );\n  }\n}\n\nmodule.exports = Upnp;\n"
  },
  {
    "path": "lib/Error.js",
    "content": "'use strict';\n\n/**\n * Exception\n *\n * Extends error for customized huejay errors\n */\nclass HuejayError extends Error {\n  /**\n   * Constructor\n   *\n   * @param {Object}  error      Error details\n   * @param {string}  fileName   Filename\n   * @param {integer} lineNumber Line number\n   */\n  constructor(error, fileName, lineNumber) {\n    let errorMessage = error.type !== undefined\n      ? `Philips Hue: ${error.type}, ${error.message}`\n      : `Huejay: ${error.message}`;\n\n    super(errorMessage, fileName, lineNumber);\n\n    this.type = error.type;\n  }\n}\n\nmodule.exports = HuejayError;\n"
  },
  {
    "path": "lib/GroupModel/AbstractGroupModel.js",
    "content": "'use strict';\n\n/**\n * Abstract group model\n */\nclass AbstractGroupModel {\n  /**\n   * Constructor\n   *\n   * @param {Object} details Group model details\n   */\n  constructor(details) {\n    this.details = Object.assign({}, details);\n  }\n\n  /**\n   * Get id of model\n   *\n   * @return {string} Id\n   */\n  get id() {\n    return this.details.id;\n  }\n\n  /**\n   * Get manufacturer\n   *\n   * @return {string} Manufacturer\n   */\n  get manufacturer() {\n    return this.details.manufacturer;\n  }\n\n  /**\n   * Get name of model\n   *\n   * @return {string} Name\n   */\n  get name() {\n    return this.details.name;\n  }\n\n  /**\n   * Get type\n   *\n   * @return {string} Type\n   */\n  get type() {\n    return this.details.type;\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Name\n   */\n  toString() {\n    return this.name;\n  }\n}\n\nmodule.exports = AbstractGroupModel;\n"
  },
  {
    "path": "lib/GroupModel/Factory.js",
    "content": "'use strict';\n\n/**\n * Factory for Group Models\n */\nclass Factory {\n  /**\n   * Create group model\n   *\n   * @param {string} modelId Model Id\n   *\n   * @return {AbstractGroupModel} GroupModel\n   */\n  static createGroupModel(modelId) {\n    let GroupModel = null;\n\n    try {\n      GroupModel = require(`./${modelId}`);\n    } catch (e) {\n      GroupModel = require('./Unknown');\n    }\n\n    return new GroupModel;\n  }\n}\n\nmodule.exports = Factory;\n"
  },
  {
    "path": "lib/GroupModel/HBL001.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HBL001',\n  manufacturer: 'Philips',\n  name:         'Hue Beyond Table',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HBL001\n */\nclass HBL001 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HBL001;\n"
  },
  {
    "path": "lib/GroupModel/HBL002.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HBL002',\n  manufacturer: 'Philips',\n  name:         'Hue Beyond Pendant',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HBL002\n */\nclass HBL002 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HBL002;\n"
  },
  {
    "path": "lib/GroupModel/HBL003.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HBL003',\n  manufacturer: 'Philips',\n  name:         'Hue Beyond Ceiling',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HBL003\n */\nclass HBL003 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HBL003;\n"
  },
  {
    "path": "lib/GroupModel/HEL001.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HEL001',\n  manufacturer: 'Philips',\n  name:         'Hue Entity Table',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HEL001\n */\nclass HEL001 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HEL001;\n"
  },
  {
    "path": "lib/GroupModel/HEL002.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HEL002',\n  manufacturer: 'Philips',\n  name:         'Hue Entity Pendant',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HEL002\n */\nclass HEL002 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HEL002;\n"
  },
  {
    "path": "lib/GroupModel/HIL001.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HIL001',\n  manufacturer: 'Philips',\n  name:         'Hue Impulse Table',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HIL001\n */\nclass HIL001 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HIL001;\n"
  },
  {
    "path": "lib/GroupModel/HIL002.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HIL002',\n  manufacturer: 'Philips',\n  name:         'Hue Impulse Pendant',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HIL002\n */\nclass HIL002 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HIL002;\n"
  },
  {
    "path": "lib/GroupModel/HML001.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HML001',\n  manufacturer: 'Philips',\n  name:         'Hue Phoenix Centerpiece',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HML001\n */\nclass HML001 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HML001;\n"
  },
  {
    "path": "lib/GroupModel/HML002.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HML002',\n  manufacturer: 'Philips',\n  name:         'Hue Phoenix Ceiling',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HML002\n */\nclass HML002 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HML002;\n"
  },
  {
    "path": "lib/GroupModel/HML003.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HML003',\n  manufacturer: 'Philips',\n  name:         'Hue Phoenix Pendant',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HML003\n */\nclass HML003 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HML003;\n"
  },
  {
    "path": "lib/GroupModel/HML004.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HML004',\n  manufacturer: 'Philips',\n  name:         'Hue Phoenix Wall',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HML004\n */\nclass HML004 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HML004;\n"
  },
  {
    "path": "lib/GroupModel/HML005.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HML005',\n  manufacturer: 'Philips',\n  name:         'Hue Phoenix Table',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HML005\n */\nclass HML005 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HML005;\n"
  },
  {
    "path": "lib/GroupModel/HML006.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HML006',\n  manufacturer: 'Philips',\n  name:         'Hue Phoenix Downlight',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HML006\n */\nclass HML006 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HML006;\n"
  },
  {
    "path": "lib/GroupModel/HML007.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           'HML007',\n  manufacturer: 'Philips',\n  name:         'Hue Phoenix Downlight',\n  type:         'Luminaire',\n};\n\n/**\n * Group model: HML007\n */\nclass HML007 extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = HML007;\n"
  },
  {
    "path": "lib/GroupModel/Unknown.js",
    "content": "'use strict';\n\nlet AbstractGroupModel = require('./AbstractGroupModel');\n\nconst DETAILS = {\n  id:           null,\n  manufacturer: null,\n  name:         null,\n  type:         null,\n};\n\n/**\n * Group model: Unknown\n */\nclass Unknown extends AbstractGroupModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = Unknown;\n"
  },
  {
    "path": "lib/Huejay.js",
    "content": "'use strict';\n\nmodule.exports = {\n  version:  require('../package.json').version,\n  discover: require('./Discovery').discoverBridges,\n  Client:   require('./Client'),\n  Error:    require('./Error')\n};\n"
  },
  {
    "path": "lib/LightModel/AbstractLightModel.js",
    "content": "'use strict';\n\n/**\n * Abstract light model\n */\nclass AbstractLightModel {\n  /**\n   * Constructor\n   *\n   * @param {Object} details Light model details\n   */\n  constructor(details) {\n    this.details = Object.assign({}, details);\n  }\n\n  /**\n   * Get id of model\n   *\n   * @return {string} Id\n   */\n  get id() {\n    return this.details.id;\n  }\n\n  /**\n   * Get manufacturer\n   *\n   * @return {string} Manufacturer\n   */\n  get manufacturer() {\n    return this.details.manufacturer;\n  }\n\n  /**\n   * Get name of model\n   *\n   * @return {string} Name\n   */\n  get name() {\n    return this.details.name;\n  }\n\n  /**\n   * Get type\n   *\n   * @return {string} Type\n   */\n  get type() {\n    return this.details.type;\n  }\n\n  /**\n   * Get color gamut\n   *\n   * @return {string} Color gamut code\n   */\n  get colorGamut() {\n    return this.details.colorGamut;\n  }\n\n  /**\n   * Friends of Hue\n   *\n   * @return {bool} True if Friends of Hue, false if not\n   */\n  get friendsOfHue() {\n    return Boolean(this.details.friendsOfHue);\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Name\n   */\n  toString() {\n    return this.name;\n  }\n}\n\nmodule.exports = AbstractLightModel;\n"
  },
  {
    "path": "lib/LightModel/Factory.js",
    "content": "'use strict';\n\n/**\n * Factory for Light Models\n */\nclass Factory {\n  /**\n   * Create light model\n   *\n   * @param {string} modelId Model Id\n   *\n   * @return {AbstractLightModel} LightModel\n   */\n  static createLightModel(modelId) {\n    let LightModel = null;\n\n    try {\n      LightModel = require(`./${modelId}`);\n    } catch (e) {\n      LightModel = require('./Unknown');\n    }\n\n    return new LightModel;\n  }\n}\n\nmodule.exports = Factory;\n"
  },
  {
    "path": "lib/LightModel/LCT001.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LCT001',\n  manufacturer: 'Philips',\n  name:         'Hue bulb A19',\n  type:         'Extended Color Light',\n  colorGamut:   'B',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LCT001\n */\nclass LCT001 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LCT001;\n"
  },
  {
    "path": "lib/LightModel/LCT002.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LCT002',\n  manufacturer: 'Philips',\n  name:         'Hue Spot BR30',\n  type:         'Extended Color Light',\n  colorGamut:   'B',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LCT002\n */\nclass LCT002 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LCT002;\n"
  },
  {
    "path": "lib/LightModel/LCT003.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LCT003',\n  manufacturer: 'Philips',\n  name:         'Hue Spot GU10',\n  type:         'Extended Color Light',\n  colorGamut:   'B',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LCT003\n */\nclass LCT003 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LCT003;\n"
  },
  {
    "path": "lib/LightModel/LCT007.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LCT007',\n  manufacturer: 'Philips',\n  name:         'Hue bulb A19',\n  type:         'Extended Color Light',\n  colorGamut:   'B',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LCT007\n */\nclass LCT007 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LCT007;\n"
  },
  {
    "path": "lib/LightModel/LCT010.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LCT010',\n  manufacturer: 'Philips',\n  name:         'Hue bulb A19',\n  type:         'Extended Color Light',\n  colorGamut:   'C',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LCT010\n */\nclass LCT010 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LCT010;\n"
  },
  {
    "path": "lib/LightModel/LCT011.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LCT011',\n  manufacturer: 'Philips',\n  name:         'Hue Spot BR30',\n  type:         'Extended Color Light',\n  colorGamut:   'C',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LCT011\n */\nclass LCT011 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LCT011;\n"
  },
  {
    "path": "lib/LightModel/LCT012.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LCT012',\n  manufacturer: 'Philips',\n  name:         'Hue color candle',\n  type:         'Extended Color Light',\n  colorGamut:   'C',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LCT012\n */\nclass LCT012 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LCT012;\n"
  },
  {
    "path": "lib/LightModel/LCT014.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LCT014',\n  manufacturer: 'Philips',\n  name:         'Hue bulb A19',\n  type:         'Extended Color Light',\n  colorGamut:   'C',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LCT014\n */\nclass LCT014 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LCT014;\n"
  },
  {
    "path": "lib/LightModel/LLC006.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLC006',\n  manufacturer: 'Philips',\n  name:         'Living Colors Gen3 Iris',\n  type:         'Color Light',\n  colorGamut:   'A',\n  friendsOfHue: false\n};\n\n/**\n * Light model: LLC006\n */\nclass LLC006 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLC006;\n"
  },
  {
    "path": "lib/LightModel/LLC007.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLC007',\n  manufacturer: 'Philips',\n  name:         'Living Colors Gen3 Bloom',\n  type:         'Color Light',\n  colorGamut:   'A',\n  friendsOfHue: false\n};\n\n/**\n * Light model: LLC007\n */\nclass LLC007 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLC007;\n"
  },
  {
    "path": "lib/LightModel/LLC010.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLC010',\n  manufacturer: 'Philips',\n  name:         'Hue Living Colors Iris',\n  type:         'Color Light',\n  colorGamut:   'A',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LLC010\n */\nclass LLC010 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLC010;\n"
  },
  {
    "path": "lib/LightModel/LLC011.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLC011',\n  manufacturer: 'Philips',\n  name:         'Hue Living Colors Bloom',\n  type:         'Color Light',\n  colorGamut:   'A',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LLC011\n */\nclass LLC011 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLC011;\n"
  },
  {
    "path": "lib/LightModel/LLC012.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLC012',\n  manufacturer: 'Philips',\n  name:         'Hue Living Colors Bloom',\n  type:         'Color Light',\n  colorGamut:   'A',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LLC012\n */\nclass LLC012 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLC012;\n"
  },
  {
    "path": "lib/LightModel/LLC013.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLC013',\n  manufacturer: 'Philips',\n  name:         'Disney Living Colors',\n  type:         'Color Light',\n  colorGamut:   'A',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LLC013\n */\nclass LLC013 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLC013;\n"
  },
  {
    "path": "lib/LightModel/LLC014.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLC014',\n  manufacturer: 'Philips',\n  name:         'Living Colors Gen3 Bloom',\n  type:         'Color Light',\n  colorGamut:   'A',\n  friendsOfHue: false\n};\n\n/**\n * Light model: LLC014\n */\nclass LLC014 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLC014;\n"
  },
  {
    "path": "lib/LightModel/LLC020.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLC020',\n  manufacturer: 'Philips',\n  name:         'Hue Go',\n  type:         'Extended Color Light',\n  colorGamut:   'C',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LLC020\n */\nclass LLC020 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLC020;\n"
  },
  {
    "path": "lib/LightModel/LLM001.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLM001',\n  manufacturer: 'Philips',\n  name:         'Color Light Module',\n  type:         'Extended Color Light',\n  colorGamut:   'B',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LLM001\n */\nclass LLM001 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLM001;\n"
  },
  {
    "path": "lib/LightModel/LLM010.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLM010',\n  manufacturer: 'Philips',\n  name:         'Color Temperature Module',\n  type:         'Color Temperature Light',\n  colorGamut:   '2200K-6500K',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LLM010\n */\nclass LLM010 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLM010;\n"
  },
  {
    "path": "lib/LightModel/LLM011.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLM011',\n  manufacturer: 'Philips',\n  name:         'Color Temperature Module',\n  type:         'Color Temperature Light',\n  colorGamut:   '2200K-6500K',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LLM011\n */\nclass LLM011 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLM011;\n"
  },
  {
    "path": "lib/LightModel/LLM012.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LLM012',\n  manufacturer: 'Philips',\n  name:         'Color Temperature Module',\n  type:         'Color Temperature Light',\n  colorGamut:   '2200K-6500K',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LLM012\n */\nclass LLM012 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LLM012;\n"
  },
  {
    "path": "lib/LightModel/LST001.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LST001',\n  manufacturer: 'Philips',\n  name:         'Hue LightStrips',\n  type:         'Color Light',\n  colorGamut:   'A',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LST001\n */\nclass LST001 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LST001;\n"
  },
  {
    "path": "lib/LightModel/LST002.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LST002',\n  manufacturer: 'Philips',\n  name:         'Hue LightStrips Plus',\n  type:         'Extended Color Light',\n  colorGamut:   'C',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LST002\n */\nclass LST002 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LST002;\n"
  },
  {
    "path": "lib/LightModel/LTW001.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LTW001',\n  manufacturer: 'Philips',\n  name:         'Hue A19 White Ambience',\n  type:         'Color Temperature Light',\n  colorGamut:   '2200K-6500K',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LTW001\n */\nclass LTW001 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LTW001;\n"
  },
  {
    "path": "lib/LightModel/LTW004.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LTW004',\n  manufacturer: 'Philips',\n  name:         'Hue A19 White Ambience',\n  type:         'Color Temperature Light',\n  colorGamut:   '2200K-6500K',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LTW004\n */\nclass LTW004 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LTW004;\n"
  },
  {
    "path": "lib/LightModel/LTW010.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LTW010',\n  manufacturer: 'Philips',\n  name:         'Hue A19 White Ambience',\n  type:         'Color Temperature Light',\n  colorGamut:   '2200K-6500K',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LTW010\n */\nclass LTW010 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LTW010;\n"
  },
  {
    "path": "lib/LightModel/LTW011.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LTW011',\n  manufacturer: 'Philips',\n  name:         'Hue BR30 White Ambience',\n  type:         'Color Temperature Light',\n  colorGamut:   '2200K-6500K',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LTW011\n */\nclass LTW011 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LTW011;\n"
  },
  {
    "path": "lib/LightModel/LTW012.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LTW012',\n  manufacturer: 'Philips',\n  name:         'Hue ambiance candle',\n  type:         'Color Temperature Light',\n  colorGamut:   '2200K-6500K',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LTW012\n */\nclass LTW012 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LTW012;\n"
  },
  {
    "path": "lib/LightModel/LTW013.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LTW013',\n  manufacturer: 'Philips',\n  name:         'Hue ambiance spot',\n  type:         'Color Temperature Light',\n  colorGamut:   '2200K-6500K',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LTW013\n */\nclass LTW013 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LTW013;\n"
  },
  {
    "path": "lib/LightModel/LTW014.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LTW014',\n  manufacturer: 'Philips',\n  name:         'Hue ambiance spot',\n  type:         'Color Temperature Light',\n  colorGamut:   '2200K-6500K',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LTW014\n */\nclass LTW014 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LTW014;\n"
  },
  {
    "path": "lib/LightModel/LTW015.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LTW015',\n  manufacturer: 'Philips',\n  name:         'Hue A19 White Ambience',\n  type:         'Color Temperature Light',\n  colorGamut:   '2200K-6500K',\n  friendsOfHue: true\n};\n\n/**\n * Light model: LTW015\n */\nclass LTW015 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LTW015;\n"
  },
  {
    "path": "lib/LightModel/LWB004.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LWB004',\n  manufacturer: 'Philips',\n  name:         'Hue A19 Lux',\n  type:         'Dimmable Light',\n  colorGamut:   null,\n  friendsOfHue: true\n};\n\n/**\n * Light model: LWB004\n */\nclass LWB004 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LWB004;\n"
  },
  {
    "path": "lib/LightModel/LWB006.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LWB006',\n  manufacturer: 'Philips',\n  name:         'Hue A19 Lux',\n  type:         'Dimmable Light',\n  colorGamut:   null,\n  friendsOfHue: true\n};\n\n/**\n * Light model: LWB006\n */\nclass LWB006 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LWB006;\n"
  },
  {
    "path": "lib/LightModel/LWB007.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LWB007',\n  manufacturer: 'Philips',\n  name:         'Hue A19 Lux',\n  type:         'Dimmable Light',\n  colorGamut:   null,\n  friendsOfHue: true\n};\n\n/**\n * Light model: LWB007\n */\nclass LWB007 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LWB007;\n"
  },
  {
    "path": "lib/LightModel/LWB010.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LWB010',\n  manufacturer: 'Philips',\n  name:         'Hue A19 Lux',\n  type:         'Dimmable Light',\n  colorGamut:   null,\n  friendsOfHue: true\n};\n\n/**\n * Light model: LWB010\n */\nclass LWB010 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LWB010;\n"
  },
  {
    "path": "lib/LightModel/LWB014.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           'LWB014',\n  manufacturer: 'Philips',\n  name:         'Hue A19 Lux',\n  type:         'Dimmable Light',\n  colorGamut:   null,\n  friendsOfHue: true\n};\n\n/**\n * Light model: LWB014\n */\nclass LWB014 extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = LWB014;\n"
  },
  {
    "path": "lib/LightModel/Unknown.js",
    "content": "'use strict';\n\nlet AbstractLightModel = require('./AbstractLightModel');\n\nconst DETAILS = {\n  id:           null,\n  manufacturer: null,\n  name:         null,\n  type:         null,\n  colorGamut:   null,\n  friendsOfHue: false\n};\n\n/**\n * Light model: Unknown\n */\nclass Unknown extends AbstractLightModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = Unknown;\n"
  },
  {
    "path": "lib/Model/Attributes.js",
    "content": "'use strict';\n\n/**\n * Attributes helper\n */\nclass Attributes {\n  /**\n   * Constructor\n   *\n   * @param {mixed} attributes Attributes (optional)\n   * @param {mixed} defaults   Default attributes (optional)\n   */\n  constructor(attributes, defaults) {\n    this.replace(Object.assign({}, defaults, attributes));\n    this.resetChanged();\n  }\n\n  /**\n   * Replace attributes\n   *\n   * @param {mixed} attributes Attributes\n   */\n  replace(attributes) {\n    this.attributes = Object.assign({}, this.attributes, attributes);\n  }\n\n  /**\n   * Get attribute\n   *\n   * @param {string} attribute Attribute\n   *\n   * @return {mixed} Value\n   */\n  get(attribute) {\n    return this.attributes[attribute];\n  }\n\n  /**\n   * Get all attributes\n   *\n   * @return {Object} Attributes/values\n   */\n  getAll() {\n    return Object.assign({}, this.attributes);\n  }\n\n  /**\n   * Set attribute to value\n   *\n   * @param {string} attribute Attribute\n   * @param {mixed}  value     Value\n   */\n  set(attribute, value) {\n    this.attributes[attribute] = value;\n\n    this.changed[attribute] = attribute;\n  }\n\n  /**\n   * Get changed attributes\n   *\n   * @return {Object} Changed attributes/values\n   */\n  getChanged() {\n    let changed = {};\n\n    for (let attribute in this.changed) {\n      changed[attribute] = this.attributes[attribute];\n    }\n\n    return changed;\n  }\n\n  /**\n   * Reset changed attributes\n   */\n  resetChanged() {\n    this.changed = {};\n  }\n}\n\nmodule.exports = Attributes;\n"
  },
  {
    "path": "lib/Model/Bridge.js",
    "content": "'use strict';\n\nlet Attributes         = require('./Attributes');\nlet BridgeModelFactory = require('../BridgeModel/Factory');\n\n/**\n * Bridge\n *\n * Bridge object\n */\nclass Bridge {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes Attributes\n   */\n  constructor(attributes) {\n    this.attributes = new Attributes(attributes);\n  }\n\n  /**\n   * Get bridge id\n   *\n   * @return {string} Bridge id\n   */\n  get id() {\n    return this.attributes.get('bridgeid');\n  }\n\n  /**\n   * Get name\n   *\n   * @return {string} Name of bridge\n   */\n  get name() {\n    return this.attributes.get('name');\n  }\n\n  /**\n   * Set name\n   *\n   * @param {string} name Name of bridge\n   */\n  set name(name) {\n    this.attributes.set('name', name);\n  }\n\n  /**\n   * Get model id\n   *\n   * @return {string} Model id\n   */\n  get modelId() {\n    return this.attributes.get('modelid');\n  }\n\n  /**\n   * Get model\n   *\n   * Lazy loads model for the bridge\n   *\n   * @return {BridgeModel} Bridge model\n   */\n  get model() {\n    if (this.bridgeModel === undefined) {\n      this.bridgeModel = BridgeModelFactory.createBridgeModel(this.modelId);\n    }\n\n    return this.bridgeModel;\n  }\n\n  /**\n   * Is factory new\n   *\n   * @return {bool} True if factory new, false if not\n   */\n  get factoryNew() {\n    return Boolean(this.attributes.get('factorynew'));\n  }\n\n  /**\n   * Get replaces bridge id\n   *\n   * @return {mixed} Bridge id, or null if none\n   */\n  get replacesBridgeId() {\n    return this.attributes.get('replacesbridgeid');\n  }\n\n  /**\n   * Get data store version\n   *\n   * @return {mixed} Data store version, or null if none\n   */\n  get dataStoreVersion() {\n    return this.attributes.get('datastoreversion');\n  }\n\n  /**\n   * Get starter kit id\n   *\n   * @return {mixed} Starter kit id, or empty string if none\n   */\n  get starterKitId() {\n    return this.attributes.get('starterkitid');\n  }\n\n  /**\n   * Get software version\n   *\n   * @return {string} Software version\n   */\n  get softwareVersion() {\n    return this.attributes.get('swversion');\n  }\n\n  /**\n   * Get API version\n   *\n   * @return {string} API version\n   */\n  get apiVersion() {\n    return this.attributes.get('apiversion');\n  }\n\n  /**\n   * Get zigbee channel\n   *\n   * @return {string} Zigbee channel\n   */\n  get zigbeeChannel() {\n    return this.attributes.get('zigbeechannel');\n  }\n\n  /**\n   * Set Zigbee channel\n   *\n   * @param {int} channel Channel\n   */\n  set zigbeeChannel(channel) {\n    this.attributes.set('zigbeechannel', Number(channel));\n  }\n\n  /**\n   * Get MAC address\n   *\n   * @return {string} MAC address\n   */\n  get macAddress() {\n    return this.attributes.get('mac');\n  }\n\n  /**\n   * Get IP Address\n   *\n   * @return {string} IP Address\n   */\n  get ipAddress() {\n    return this.attributes.get('ipaddress');\n  }\n\n  /**\n   * Set IP Address\n   *\n   * @param {string} ipAddress IP Address\n   */\n  set ipAddress(ipAddress) {\n    this.attributes.set('ipaddress', String(ipAddress));\n  }\n\n  /**\n   * Is DHCP enabled\n   *\n   * @return {bool} True if enabled, false if not\n   */\n  get dhcpEnabled() {\n    return Boolean(this.attributes.get('dhcp'));\n  }\n\n  /**\n   * Enable DHCP\n   *\n   * @param {bool} True to enable, false to disable\n   */\n  set dhcpEnabled(value) {\n    this.attributes.set('dhcp', Boolean(value));\n  }\n\n  /**\n   * Get netmask\n   *\n   * @return {string} Netmask\n   */\n  get netmask() {\n    return this.attributes.get('netmask');\n  }\n\n  /**\n   * Set netmask\n   *\n   * @param {string} mask Network mask\n   */\n  set netmask(mask) {\n    this.attributes.set('netmask', String(mask));\n  }\n\n\n  /**\n   * Get gateway\n   *\n   * @return {string} Gateway\n   */\n  get gateway() {\n    return this.attributes.get('gateway');\n  }\n\n  /**\n   * Set gateway\n   *\n   * @param {string} address Address\n   */\n  set gateway(address) {\n    this.attributes.set('gateway', String(address));\n  }\n\n  /**\n   * Get proxy address\n   *\n   * @return {mixed} Proxy address\n   */\n  get proxyAddress() {\n    let proxyAddress = this.attributes.get('proxyaddress');\n\n    return proxyAddress === 'none'\n      ? undefined\n      : proxyAddress;\n  }\n\n  /**\n   * Set proxy address\n   *\n   * @param {string} address Address\n   */\n  set proxyAddress(address) {\n    this.attributes.set('proxyaddress', String(address));\n  }\n\n  /**\n   * Get proxy port\n   *\n   * @return {mixed} Proxy port if set, undefined if not\n   */\n  get proxyPort() {\n    let proxyPort = this.attributes.get('proxyport');\n\n    return proxyPort === 0\n      ? undefined\n      : proxyPort;\n  }\n\n  /**\n   * Set proxy port\n   *\n   * @param {int} port Port\n   */\n  set proxyPort(port) {\n    this.attributes.set('proxyport', Number(port));\n  }\n\n  /**\n   * Get utc time\n   *\n   * @return {string} UTC time\n   */\n  get utcTime() {\n    return this.attributes.get('UTC');\n  }\n\n  /**\n   * Get time zone\n   *\n   * @return {string} Time zone\n   */\n  get timeZone() {\n    let timeZone = this.attributes.get('timezone');\n\n    return timeZone === 'none'\n      ? undefined\n      : timeZone;\n  }\n\n  /**\n   * Set time zone\n   *\n   * @param {string} timeZone Time zone\n   */\n  set timeZone(timeZone) {\n    this.attributes.set('timezone', String(timeZone));\n  }\n\n  /**\n   * Get local time\n   *\n   * @return {string} Local time\n   */\n  get localTime() {\n    let localTime = this.attributes.get('localtime');\n\n    return localTime === 'none'\n      ? undefined\n      : localTime;\n  }\n\n  /**\n   * Is portal services enabled\n   *\n   * @return {bool} True if enabled, false if not\n   */\n  get portalServicesEnabled() {\n    return Boolean(this.attributes.get('portalservices'));\n  }\n\n  /**\n   * Is portal connected\n   *\n   * @return {bool} True if connected, false if not\n   */\n  get portalConnected() {\n    return this.attributes.get('portalconnection') === 'connected';\n  }\n\n  /**\n   * Get link button state\n   *\n   * @return {bool} True if enabled, faise if not\n   */\n  get linkButtonEnabled() {\n    return Boolean(this.attributes.get('linkbutton'));\n  }\n\n  /**\n   * Enable link button\n   *\n   * @param {bool} value True to enable, false to disable\n   */\n  set linkButtonEnabled(value) {\n    this.attributes.set('linkbutton', Boolean(value));\n  }\n\n  /**\n   * Get Touchlink state\n   *\n   * @return {bool} True if enabled, faise if not\n   */\n  get touchlinkEnabled() {\n    return Boolean(this.attributes.get('touchlink'));\n  }\n\n  /**\n   * Enable Touchlink\n   *\n   * @param {bool} value True to enable, false to disable\n   */\n  set touchlinkEnabled(value) {\n    this.attributes.set('touchlink', Boolean(value));\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Bridge Id\n   */\n  toString() {\n    return this.id;\n  }\n}\n\nmodule.exports = Bridge;\n"
  },
  {
    "path": "lib/Model/Condition.js",
    "content": "'use strict';\n\nlet moment  = require('moment');\n\nlet SensorUtils = require('../Command/Sensor/Utils');\n\nconst DEFAULT_CONDITION = {\n  sensor:    null,\n  attribute: null,\n  operator:  null,\n  value:     null,\n};\n\n/**\n * Condition\n *\n * Condition object\n */\nclass Condition {\n  /**\n   * Constructor\n   *\n   * @param {Object} condition Condition\n   */\n  constructor(condition) {\n    this.condition = Object.assign({}, DEFAULT_CONDITION);\n  }\n\n  /**\n   * Get sensor\n   *\n   * @return {mixed} Sensor\n   */\n  get sensor() {\n    return this.condition.sensor;\n  }\n\n  /**\n   * Set sensor\n   *\n   * @param {Sensor} sensor Sensor\n   */\n  set sensor(sensor) {\n    SensorUtils.validateSensor(sensor);\n\n    this.condition.sensor = sensor;\n  }\n\n  /**\n   * Get attribute\n   *\n   * @return {string} Attribute\n   */\n  get attribute() {\n    return this.condition.attribute;\n  }\n\n  /**\n   * Set attribute\n   *\n   * @param {string} attribute Attribute\n   */\n  set attribute(attribute) {\n    this.condition.attribute = String(attribute);\n  }\n\n  /**\n   * Get operator\n   *\n   * @return {string} Operator\n   */\n  get operator() {\n    return this.condition.operator;\n  }\n\n  /**\n   * Set operator\n   *\n   * @param {string} operator Operator\n   */\n  set operator(operator) {\n    this.condition.operator = String(operator);\n  }\n\n  /**\n   * Get value\n   *\n   * @return {mixed} Value\n   */\n  get value() {\n    return this.condition.value;\n  }\n\n  /**\n   * Set value\n   *\n   * @param {mixed} value Value\n   */\n  set value(value) {\n    this.condition.value = value;\n  }\n\n  /**\n   * When (field changes)\n   *\n   * @param {string} attribute State attribute\n   *\n   * @return {Condition} This object\n   */\n  when(attribute) {\n    let stateMap = this.sensor.state.stateMap;\n\n    this.attribute = (attribute in stateMap)\n      ? stateMap[attribute]\n      : String(attribute);\n\n    return this;\n  }\n\n  /**\n   * Greater than value\n   *\n   * @param {string} value Value\n   */\n  greaterThan(value) {\n    this.operator = 'gt';\n    this.value    = String(value);\n  }\n\n  /**\n   * Less than value\n   *\n   * @param {string} value Value\n   */\n  lessThan(value) {\n    this.operator = 'lt';\n    this.value    = String(value);\n  }\n\n  /**\n   * Equals value\n   *\n   * @param {string} value Value\n   */\n  equals(value) {\n    this.operator = 'eq';\n    this.value    = String(value);\n  }\n\n  /**\n   * Changes (value changes)\n   */\n  changes() {\n    this.operator = 'dx';\n    this.value    = undefined;\n  }\n\n  /**\n   * Delayed changes\n   */\n  delayedChanges() {\n    this.operator = 'ddx';\n    this.value    = undefined;\n  }\n\n  /**\n   * Stable for (time)\n   *\n   * @param {int} time Time\n   */\n  stableFor(time) {\n    this.operator = 'stable';\n    this.value    = time;\n  }\n\n  /**\n   * Unstable for (time)\n   *\n   * @param {int} time Time\n   */\n  unstableFor(time) {\n    this.operator = 'not stable';\n    this.value    = time;\n  }\n\n  /**\n   * In (time)\n   * \n   * @param {string} startTime Time\n   * @param {string} endTime   Time\n   */\n  in(startTime, endTime) {\n    let startHour = moment(startTime).format('[T]HH:mm:ss');\n    let endHour   = moment(endTime).format('[T]HH:mm:ss');\n\n    this.operator = 'in';\n    this.value    = `${startHour}/${endHour}`;\n  }\n\n  /**\n   * Not in (time)\n   * \n   * @param {string} startTime Time\n   * @param {string} endTime   Time\n   */\n  notIn(startTime, endTime) {\n    let startHour = moment(startTime).format('[T]HH:mm:ss');\n    let endHour   = moment(endTime).format('[T]HH:mm:ss');\n\n    this.operator = 'not in';\n    this.value    = `${startHour}/${endHour}`;\n  }\n}\n\nmodule.exports = Condition;\n"
  },
  {
    "path": "lib/Model/Group.js",
    "content": "'use strict';\n\nlet Attributes        = require('./Attributes');\nlet GroupModelFactory = require('../GroupModel/Factory');\n\nconst DEFAULT_ATTRIBUTES = {\n  'type':  'LightGroup',\n  'lights': [],\n};\n\n/**\n * Group\n *\n * Group object\n */\nclass Group {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes Attributes\n   * @param {Object} state      State\n   * @param {Object} action     Action\n   */\n  constructor(attributes, state, action) {\n    this.attributes = new Attributes(attributes, DEFAULT_ATTRIBUTES);\n    this.state      = new Attributes(state);\n    this.action     = new Attributes(action);\n  }\n\n  /**\n   * Get group id\n   *\n   * @return {string} Group id\n   */\n  get id() {\n    return this.attributes.get('id');\n  }\n\n  /**\n   * Get name\n   *\n   * @return {string} Name\n   */\n  get name() {\n    return this.attributes.get('name');\n  }\n\n  /**\n   * Set name\n   *\n   * @param {string} name Name\n   */\n  set name(name) {\n    this.attributes.set('name', String(name));\n  }\n\n  /**\n   * Get type\n   *\n   * @return {string} Type\n   */\n  get type() {\n    return this.attributes.get('type');\n  }\n\n  /**\n   * Set type\n   *\n   * @param {string} type Type\n   */\n  set type(type) {\n    this.attributes.set('type', String(type));\n  }\n\n  /**\n   * Get class\n   *\n   * @return {string} Class\n   */\n  get class() {\n    return this.attributes.get('class');\n  }\n\n  /**\n   * Set class\n   *\n   * @return {string} typeClass Class\n   */\n  set class(typeClass) {\n    this.attributes.set('class', String(typeClass));\n  }\n\n  /**\n   * Get light ids\n   *\n   * @return {array} List of light ids\n   */\n  get lightIds() {\n    return this.attributes.get('lights');\n  }\n\n  /**\n   * Set light ids\n   *\n   * @param {array} lights List of light ids or Light objects\n   */\n  set lightIds(lights) {\n    let lightIds = lights.map(light => {\n      return String(light);\n    });\n\n    this.attributes.set('lights', lightIds);\n  }\n\n  /**\n   * Get model id\n   *\n   * @return {mixed} Model Id if available\n   */\n  get modelId() {\n    return this.attributes.get('modelid');\n  }\n\n  /**\n   * Get model\n   *\n   * Lazy loads model for the group\n   *\n   * @return {GroupModel} Group model\n   */\n  get model() {\n    if (this.modelId !== undefined && this.groupModel === undefined) {\n      this.groupModel = GroupModelFactory.createGroupModel(this.modelId);\n    }\n\n    return this.groupModel;\n  }\n\n  /**\n   * Get unique Id\n   *\n   * @return {string} Unique Id\n   */\n  get uniqueId() {\n    return this.attributes.get('uniqueid');\n  }\n\n  /**\n   * Get on\n   *\n   * @return {bool} True if on, false if not\n   */\n  get on() {\n    return Boolean(this.action.get('on'));\n  }\n\n  /**\n   * Set on\n   *\n   * @param {bool} value True for on, false if not\n   */\n  set on(value) {\n    this.action.set('on', Boolean(value));\n  }\n\n  /**\n   * Get brightness\n   *\n   * @return {int} Brightness\n   */\n  get brightness() {\n    return this.action.get('bri');\n  }\n\n  /**\n   * Set brightness\n   *\n   * @param {int} brightness Brightness\n   */\n  set brightness(brightness) {\n    this.action.set('bri', Number(brightness));\n  }\n\n  /**\n   * Get color mode\n   *\n   * @return {string} Color mode\n   */\n  get colorMode() {\n    return this.action.get('colormode');\n  }\n\n  /**\n   * Get hue\n   *\n   * @return {int} Hue\n   */\n  get hue() {\n    return this.action.get('hue');\n  }\n\n  /**\n   * Set hue\n   *\n   * @param {int} hue Hue\n   */\n  set hue(hue) {\n    this.action.set('hue', Number(hue));\n  }\n\n  /**\n   * Get saturation\n   *\n   * @return {int} Saturation\n   */\n  get saturation() {\n    return this.action.get('sat');\n  }\n\n  /**\n   * Set saturation\n   *\n   * @param {int} saturation Saturation\n   */\n  set saturation(saturation) {\n    this.action.set('sat', Number(saturation));\n  }\n\n  /**\n   * Get x/y\n   *\n   * @return {array} X/Y\n   */\n  get xy() {\n    return this.action.get('xy');\n  }\n\n  /**\n   * Set x/y\n   *\n   * @param {array} xy X/Y\n   */\n  set xy(xy) {\n    this.action.set('xy', xy);\n  }\n\n  /**\n   * Get color temperature\n   *\n   * @return {int} Temperature\n   */\n  get colorTemp() {\n    return this.action.get('ct');\n  }\n\n  /**\n   * Set color temperature\n   *\n   * @param {int} temp Temperature\n   */\n  set colorTemp(temp) {\n    this.action.set('ct', Number(temp));\n  }\n\n  /**\n   * Get alert\n   *\n   * @return {string} Alert\n   */\n  get alert() {\n    return this.action.get('alert');\n  }\n\n  /**\n   * Set alert\n   *\n   * @param {string} mode Mode\n   */\n  set alert(mode) {\n    this.action.set('alert', String(mode));\n  }\n\n  /**\n   * Get effect\n   *\n   * @return {string} Effect\n   */\n  get effect() {\n    return this.action.get('effect');\n  }\n\n  /**\n   * Set effect\n   *\n   * @param {string} effect Effect\n   */\n  set effect(effect) {\n    this.action.set('effect', String(effect));\n  }\n\n  /**\n   * Get scene\n   *\n   * @return {string} Scene\n   */\n  get scene() {\n    return this.action.get('scene');\n  }\n\n  /**\n   * Set scene\n   *\n   * @param {string} scene Scene\n   */\n  set scene(scene) {\n    this.action.set('scene', String(scene));\n  }\n\n  /**\n   * Get transition time\n   *\n   * @return {int} Transition time\n   */\n  get transitionTime() {\n    return this.action.get('transitiontime') / 10;\n  }\n\n  /**\n   * Set transition time\n   *\n   * @param {int} time Time in seconds\n   */\n  set transitionTime(time) {\n    this.action.set('transitiontime', Number(time) * 10);\n  }\n\n  /**\n   * Get increment brightness\n   *\n   * @return {int} Brightness increment amount\n   */\n  get incrementBrightness() {\n    return this.action.get('bri_inc');\n  }\n\n  /**\n   * Set increment brightness\n   *\n   * @param {int} amount Amount\n   */\n  set incrementBrightness(amount) {\n    this.action.set('bri_inc', Number(amount));\n  }\n\n  /**\n   * Get increment hue\n   *\n   * @return {int} Hue increment amount\n   */\n  get incrementHue() {\n    return this.action.get('hue_inc');\n  }\n\n  /**\n   * Set increment hue\n   *\n   * @param {int} amount Amount\n   */\n  set incrementHue(amount) {\n    this.action.set('hue_inc', Number(amount));\n  }\n\n  /**\n   * Get increment saturation\n   *\n   * @return {int} Saturation increment amount\n   */\n  get incrementSaturation() {\n    return this.action.get('sat_inc');\n  }\n\n  /**\n   * Set increment saturation\n   *\n   * @param {int} amount Amount\n   */\n  set incrementSaturation(amount) {\n    this.action.set('sat_inc', Number(amount));\n  }\n\n  /**\n   * Get increment XY\n   *\n   * @return {float} XY increment amount\n   */\n  get incrementXy() {\n    return this.action.get('xy_inc');\n  }\n\n  /**\n   * Set increment XY\n   *\n   * @param {float} amount Amount\n   */\n  set incrementXy(amount) {\n    this.action.set('xy_inc', parseFloat(amount));\n  }\n\n  /**\n   * Get increment color temp\n   *\n   * @return {int} Color temp increment amount\n   */\n  get incrementColorTemp() {\n    return this.action.get('ct_inc');\n  }\n\n  /**\n   * Set increment color temp\n   *\n   * @param {int} amount Amount\n   */\n  set incrementColorTemp(amount) {\n    this.action.set('ct_inc', Number(amount));\n  }\n\n  /**\n   * Any lights on in group?\n   *\n   * @return {bool} True if any lights are on in the group, false if not\n   */\n  get anyOn() {\n    return this.state.get('any_on');\n  }\n\n  /**\n   * All lights on in group?\n   *\n   * @return {bool} True if all lights are on in the group, false if not\n   */\n  get allOn() {\n    return this.state.get('all_on');\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Id\n   */\n  toString() {\n    return this.id;\n  }\n}\n\nmodule.exports = Group;\n"
  },
  {
    "path": "lib/Model/InternetServices.js",
    "content": "'use strict';\n\nlet Attributes = require('./Attributes');\n\n/**\n * Internet services object\n *\n * Internet services details\n */\nclass InternetServices {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes Attributes\n   */\n  constructor(attributes) {\n    this.attributes = new Attributes(attributes);\n  }\n\n  /**\n   * Internet connected?\n   *\n   * @return {Boolean} True if connected, false if not\n   */\n  get internetConnected() {\n    return this.attributes.get('internet') == 'connected';\n  }\n\n  /**\n   * Remote access connected?\n   *\n   * @return {Boolean} True if connected, false if not\n   */\n  get remoteAccessConnected() {\n    return this.attributes.get('remoteaccess') == 'connected';\n  }\n\n  /**\n   * Time sync connected?\n   *\n   * @return {Boolean} True if connected, false if not\n   */\n  get timeSyncConnected() {\n    return this.attributes.get('time') == 'connected';\n  }\n\n  /**\n   * Time sync connected?\n   *\n   * @return {Boolean} True if connected, false if not\n   */\n  get softwareUpdateConnected() {\n    return this.attributes.get('swupdate') == 'connected';\n  }\n}\n\nmodule.exports = InternetServices;"
  },
  {
    "path": "lib/Model/Light.js",
    "content": "'use strict';\n\nlet Attributes        = require('./Attributes');\nlet LightModelFactory = require('../LightModel/Factory');\n\n/**\n * Light\n *\n * Light object\n */\nclass Light {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes Attributes\n   * @param {Object} state      State\n   */\n  constructor(attributes, state) {\n    this.attributes = new Attributes(attributes);\n    this.state      = new Attributes(state);\n  }\n\n  /**\n   * Get light id\n   *\n   * @return {string} Light id\n   */\n  get id() {\n    return this.attributes.get('id');\n  }\n\n  /**\n   * Get name\n   *\n   * @return {string} Name\n   */\n  get name() {\n    return this.attributes.get('name');\n  }\n\n  /**\n   * Set name\n   *\n   * @param {string} name Name\n   */\n  set name(name) {\n    this.attributes.set('name', String(name));\n  }\n\n  /**\n   * Get type\n   *\n   * @return {string} Type\n   */\n  get type() {\n    return this.attributes.get('type');\n  }\n\n  /**\n   * Get unique id\n   *\n   * @return {string} Unique id\n   */\n  get uniqueId() {\n    return this.attributes.get('uniqueid');\n  }\n\n  /**\n   * Get manufacturer\n   *\n   * @return {string} Manufacturer\n   */\n  get manufacturer() {\n    return this.attributes.get('manufacturername');\n  }\n\n  /**\n   * Get model id\n   *\n   * @return {string} Model id\n   */\n  get modelId() {\n    return this.attributes.get('modelid');\n  }\n\n  /**\n   * Get model\n   *\n   * Lazy loads model for the light\n   *\n   * @return {LightModel} Light model\n   */\n  get model() {\n    if (this.lightModel === undefined) {\n      this.lightModel = LightModelFactory.createLightModel(this.modelId);\n    }\n\n    return this.lightModel;\n  }\n\n  /**\n   * Get product id\n   *\n   * @return {string} Product id\n   */\n  get productId() {\n    return this.attributes.get('productid');\n  }\n\n  /**\n   * Get software version\n   *\n   * @return {string} Software version\n   */\n  get softwareVersion() {\n    return this.attributes.get('swversion');\n  }\n\n  /**\n   * Get software config id\n   *\n   * @return {string} Software config id\n   */\n  get softwareConfigId() {\n    return this.attributes.get('swconfigid');\n  }\n\n  /**\n   * Get on\n   *\n   * @return {bool} True if on, false if not\n   */\n  get on() {\n    return Boolean(this.state.get('on'));\n  }\n\n  /**\n   * Set on\n   *\n   * @param {bool} value True for on, false if not\n   */\n  set on(value) {\n    this.state.set('on', Boolean(value));\n  }\n\n  /**\n   * Get reachable\n   *\n   * @return {bool} Reachable\n   */\n  get reachable() {\n    return this.state.get('reachable');\n  }\n\n  /**\n   * Get brightness\n   *\n   * @return {int} Brightness\n   */\n  get brightness() {\n    return this.state.get('bri');\n  }\n\n  /**\n   * Set brightness\n   *\n   * @param {int} brightness Brightness\n   */\n  set brightness(brightness) {\n    this.state.set('bri', Number(brightness));\n  }\n\n  /**\n   * Get color mode\n   *\n   * @return {string} Color mode\n   */\n  get colorMode() {\n    return this.state.get('colormode');\n  }\n\n  /**\n   * Get hue\n   *\n   * @return {int} Hue\n   */\n  get hue() {\n    return this.state.get('hue');\n  }\n\n  /**\n   * Set hue\n   *\n   * @param {int} hue Hue\n   */\n  set hue(hue) {\n    this.state.set('hue', Number(hue));\n  }\n\n  /**\n   * Get saturation\n   *\n   * @return {int} Saturation\n   */\n  get saturation() {\n    return this.state.get('sat');\n  }\n\n  /**\n   * Set saturation\n   *\n   * @param {int} saturation Saturation\n   */\n  set saturation(saturation) {\n    this.state.set('sat', Number(saturation));\n  }\n\n  /**\n   * Get x/y\n   *\n   * @return {array} X/Y\n   */\n  get xy() {\n    return this.state.get('xy');\n  }\n\n  /**\n   * Set x/y\n   *\n   * @param {array} xy X/Y\n   */\n  set xy(xy) {\n    this.state.set('xy', xy);\n  }\n\n  /**\n   * Get color temperature\n   *\n   * @return {int} Temperature\n   */\n  get colorTemp() {\n    return this.state.get('ct');\n  }\n\n  /**\n   * Set color temperature\n   *\n   * @param {int} temp Temperature\n   */\n  set colorTemp(temp) {\n    this.state.set('ct', Number(temp));\n  }\n\n  /**\n   * Get alert\n   *\n   * @return {string} Alert\n   */\n  get alert() {\n    return this.state.get('alert');\n  }\n\n  /**\n   * Set alert\n   *\n   * @param {string} mode Mode\n   */\n  set alert(mode) {\n    this.state.set('alert', String(mode));\n  }\n\n  /**\n   * Get effect\n   *\n   * @return {string} Effect\n   */\n  get effect() {\n    return this.state.get('effect');\n  }\n\n  /**\n   * Set effect\n   *\n   * @param {string} effect Effect\n   */\n  set effect(effect) {\n    this.state.set('effect', String(effect));\n  }\n\n  /**\n   * Get transition time\n   *\n   * @return {int} Transition time\n   */\n  get transitionTime() {\n    return this.state.get('transitiontime') / 10;\n  }\n\n  /**\n   * Set transition time\n   *\n   * @param {int} time Time in seconds\n   */\n  set transitionTime(time) {\n    this.state.set('transitiontime', Number(time) * 10);\n  }\n\n  /**\n   * Get increment brightness\n   *\n   * @return {int} Brightness increment amount\n   */\n  get incrementBrightness() {\n    return this.state.get('bri_inc');\n  }\n\n  /**\n   * Set increment brightness\n   *\n   * @param {int} amount Amount\n   */\n  set incrementBrightness(amount) {\n    this.state.set('bri_inc', Number(amount));\n  }\n\n  /**\n   * Get increment hue\n   *\n   * @return {int} Hue increment amount\n   */\n  get incrementHue() {\n    return this.state.get('hue_inc');\n  }\n\n  /**\n   * Set increment hue\n   *\n   * @param {int} amount Amount\n   */\n  set incrementHue(amount) {\n    this.state.set('hue_inc', Number(amount));\n  }\n\n  /**\n   * Get increment saturation\n   *\n   * @return {int} Saturation increment amount\n   */\n  get incrementSaturation() {\n    return this.state.get('sat_inc');\n  }\n\n  /**\n   * Set increment saturation\n   *\n   * @param {int} amount Amount\n   */\n  set incrementSaturation(amount) {\n    this.state.set('sat_inc', Number(amount));\n  }\n\n  /**\n   * Get increment XY\n   *\n   * @return {float} XY increment amount\n   */\n  get incrementXy() {\n    return this.state.get('xy_inc');\n  }\n\n  /**\n   * Set increment XY\n   *\n   * @param {float} amount Amount\n   */\n  set incrementXy(amount) {\n    this.state.set('xy_inc', parseFloat(amount));\n  }\n\n  /**\n   * Get increment color temp\n   *\n   * @return {int} Color temp increment amount\n   */\n  get incrementColorTemp() {\n    return this.state.get('ct_inc');\n  }\n\n  /**\n   * Set increment color temp\n   *\n   * @param {int} amount Amount\n   */\n  set incrementColorTemp(amount) {\n    this.state.set('ct_inc', Number(amount));\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Id\n   */\n  toString() {\n    return this.id;\n  }\n}\n\nmodule.exports = Light;\n"
  },
  {
    "path": "lib/Model/Portal.js",
    "content": "'use strict';\n\nlet Attributes = require('./Attributes');\n\n/**\n * Portal object\n *\n * Portal connectivity details\n */\nclass Portal {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes Attributes\n   */\n  constructor(attributes) {\n    this.attributes = new Attributes(attributes);\n  }\n\n  /**\n   * Is signed on\n   *\n   * @return {Boolean} True if signed on, false if not\n   */\n  get signedOn() {\n    return Boolean(this.attributes.get('signedon'));\n  }\n\n  /**\n   * Is incoming\n   *\n   * @return {Boolean} True if incoming, false if not\n   */\n  get incoming() {\n    return Boolean(this.attributes.get('incoming'));\n  }\n\n  /**\n   * Is outgoing\n   *\n   * @return {Boolean} True if outgoing, false if not\n   */\n  get outgoing() {\n    return Boolean(this.attributes.get('outgoing'));\n  }\n\n  /**\n   * Get communication\n   *\n   * @return {string} Communication type\n   */\n  get communication() {\n    return this.attributes.get('communication');\n  }\n}\n\nmodule.exports = Portal;\n"
  },
  {
    "path": "lib/Model/ResourceLink.js",
    "content": "'use strict';\n\nlet Attributes = require('./Attributes');\n\nconst DEFAULT_ATTRIBUTES = {\n  'type':    'Link',\n  'classid': 0,\n  'recycle': false,\n  'links':   []\n};\n\n/**\n * Resource link\n *\n * Resource link object\n */\nclass ResourceLink {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes Attributes\n   */\n  constructor(attributes) {\n    this.attributes  = new Attributes(attributes, DEFAULT_ATTRIBUTES);\n  }\n\n  /**\n   * Get id\n   *\n   * @return {string} Id\n   */\n  get id() {\n    return this.attributes.get('id');\n  }\n\n  /**\n   * Get name\n   *\n   * @return {string} Name\n   */\n  get name() {\n    return this.attributes.get('name');\n  }\n\n  /**\n   * Set name\n   *\n   * @param {string} name Name\n   */\n  set name(name) {\n    this.attributes.set('name', String(name));\n  }\n\n  /**\n   * Get description\n   *\n   * @return {string} Description\n   */\n  get description() {\n    return this.attributes.get('description');\n  }\n\n  /**\n   * Set description\n   *\n   * @param {string} description Description\n   */\n  set description(description) {\n    this.attributes.set('description', String(description));\n  }\n\n  /**\n   * Get type\n   *\n   * @return {string} Type\n   */\n  get type() {\n    return this.attributes.get('type');\n  }\n\n  /**\n   * Get class id\n   *\n   * @return {int} Class Id\n   */\n  get classId() {\n    return this.attributes.get('classid');\n  }\n\n  /**\n   * Set class id\n   *\n   * @param {string} classId Class Id\n   */\n  set classId(classId) {\n    this.attributes.set('classid', Number(classId));\n  }\n\n  /**\n   * Get owner\n   *\n   * @return {string} Owner\n   */\n  get owner() {\n    return this.attributes.get('owner');\n  }\n\n  /**\n   * Get recycle\n   *\n   * @return {bool} Recycle\n   */\n  get recycle() {\n    return this.attributes.get('recycle');\n  }\n\n  /**\n   * Set recycle\n   *\n   * @param {bool} value True to automatically delete on no reference\n   */\n  set recycle(value) {\n    this.attributes.set('recycle', Boolean(value));\n  }\n\n  /**\n   * Get links\n   *\n   * @return {array} List of resource paths\n   */\n  get links() {\n    return this.attributes.get('links');\n  }\n\n  /**\n   * Set links\n   *\n   * @param {array} links List of resource paths\n   */\n  set links(links) {\n    this.attributes.set('links', links);\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Id\n   */\n  toString() {\n    return this.id;\n  }\n}\n\nmodule.exports = ResourceLink;\n"
  },
  {
    "path": "lib/Model/Rule.js",
    "content": "'use strict';\n\nlet Attributes     = require('./Attributes');\nlet AbstractAction = require('../Action/AbstractAction');\nlet Condition      = require('./Condition');\nlet Error          = require('../Error');\n\nconst MAX_CONDITIONS     = 8;\nconst MAX_ACTIONS        = 8;\nconst DEFAULT_ATTRIBUTES = {\n  status:     'enabled',\n  conditions: [],\n  actions:    [],\n};\n\n/**\n * Rule\n *\n * Rule object\n */\nclass Rule {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes Attributes\n   */\n  constructor(attributes) {\n    this.attributes = new Attributes(attributes, DEFAULT_ATTRIBUTES);\n  }\n\n  /**\n   * Get Id\n   *\n   * @return {string} Id\n   */\n  get id() {\n    return this.attributes.get('id');\n  }\n\n  /**\n   * Get name\n   *\n   * @return {string} Name\n   */\n  get name() {\n    return this.attributes.get('name');\n  }\n\n  /**\n   * Set name\n   *\n   * @param {string} name Name\n   */\n  set name(name) {\n    this.attributes.set('name', String(name));\n  }\n\n  /**\n   * Get created time\n   *\n   * @return {string} Date\n   */\n  get created() {\n    return this.attributes.get('created');\n  }\n\n  /**\n   * Get last triggered date\n   *\n   * @return {mixed} Date string, or null if none\n   */\n  get lastTriggered() {\n    return this.attributes.get('lasttriggered') !== 'none'\n      ? this.attributes.get('lasttriggered')\n      : null\n  }\n\n  /**\n   * Times triggered\n   *\n   * @return {int} Number of times triggered\n   */\n  get timesTriggered() {\n    return this.attributes.get('timestriggered');\n  }\n\n  /**\n   * Get owner\n   *\n   * @return {string} Owner\n   */\n  get owner() {\n    return this.attributes.get('owner');\n  }\n\n  /**\n   * Get status\n   *\n   * @return {string} Status\n   */\n  get status() {\n    return this.attributes.get('status');\n  }\n\n  /**\n   * Set status\n   *\n   * @param {string} value Value\n   */\n  set status(value) {\n    value = (value === 'enabled')\n      ? 'enabled'\n      : 'disabled';\n\n    this.attributes.set('status', value);\n  }\n\n  /**\n   * Get conditions\n   *\n   * @return {array} Conditions\n   */\n  get conditions() {\n    return this.attributes.get('conditions');\n  }\n\n  /**\n   * Set conditions\n   *\n   * @param {Array} conditions Conditions\n   */\n  set conditions(conditions) {\n    this.attributes.set('conditions', conditions);\n  }\n\n  /**\n   * Add condition\n   *\n   * @param {Sensor} Sensor or Sensor Id\n   *\n   * @return {Condition} Condition\n   */\n  addCondition(sensor) {\n    let conditions = this.conditions;\n\n    if ((conditions.length + 1) > MAX_CONDITIONS) {\n      throw new Error({\n        message: `May not add more than ${MAX_CONDITIONS} conditions to Rule`\n      });\n    }\n\n    // Initialize condition\n    let condition = new Condition;\n    condition.sensor = sensor;\n\n    // Add to existing conditions\n    conditions.push(condition);\n\n    this.conditions = conditions;\n\n    return condition;\n  }\n\n  /**\n   * Clear conditions\n   */\n  clearConditions() {\n    this.conditions = [];\n  }\n\n  /**\n   * Get actions\n   *\n   * @return {array} Array\n   */\n  get actions() {\n    return this.attributes.get('actions');\n  }\n\n  /**\n   * Set actions\n   *\n   * @param {Array} actions Actions\n   */\n  set actions(actions) {\n    return this.attributes.set('actions', actions);\n  }\n\n  /**\n   * Add action\n   *\n   * @param {Object} action Action\n   */\n  addAction(action) {\n    if (!(action instanceof AbstractAction)) {\n      throw new Error({\n        message: 'Expecting Action'\n      });\n    }\n\n    let actions = this.actions;\n\n    if ((actions.length + 1) > MAX_ACTIONS) {\n      throw new Error({\n        message: `May not add more than ${MAX_ACTIONS} actions to Rule`\n      });\n    }\n\n    actions.push(action);\n\n    this.actions = actions;\n  }\n\n  /**\n   * Clear actions\n   */\n  clearActions() {\n    this.actions = [];\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Id\n   */\n  toString() {\n    return this.id;\n  }\n}\n\nmodule.exports = Rule;\n"
  },
  {
    "path": "lib/Model/Scene.js",
    "content": "'use strict';\n\nlet Attributes = require('./Attributes');\n\nconst DEFAULT_ATTRIBUTES = {\n  'lights': []\n};\n\n/**\n * Scene\n *\n * Scene object\n */\nclass Scene {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes  Attributes\n   * @param {Object} lightStates Light states\n   */\n  constructor(attributes, lightStates) {\n    this.attributes  = new Attributes(attributes, DEFAULT_ATTRIBUTES);\n    this.lightStates = new Attributes(lightStates);\n  }\n\n  /**\n   * Get id\n   *\n   * @return {string} Id\n   */\n  get id() {\n    return this.attributes.get('id');\n  }\n\n  /**\n   * Get name\n   *\n   * @return {string} Name\n   */\n  get name() {\n    return this.attributes.get('name');\n  }\n\n  /**\n   * Set name\n   *\n   * @param {string} name Name\n   */\n  set name(name) {\n    this.attributes.set('name', String(name));\n  }\n\n  /**\n   * Get light ids\n   *\n   * @return {array} List of light ids\n   */\n  get lightIds() {\n    return this.attributes.get('lights');\n  }\n\n  /**\n   * Set light ids\n   *\n   * @param {array} lights List of light ids or Light objects\n   */\n  set lightIds(lights) {\n    let lightIds = lights.map(light => {\n      return String(light);\n    });\n\n    this.attributes.set('lights', lightIds);\n  }\n\n  /**\n   * Get owner\n   *\n   * @return {string} Owner\n   */\n  get owner() {\n    return this.attributes.get('owner');\n  }\n\n  /**\n   * Get recycle\n   *\n   * @return {boolean} True to recycle on limit, false to require delete\n   */\n  get recycle() {\n    return this.attributes.get('recycle');\n  }\n\n  /**\n   * Set recycle\n   *\n   * @param {boolean} value True to recycle on limit, false to require delete\n   */\n  set recycle(value) {\n    this.attributes.set('recycle', Boolean(value));\n  }\n\n  /**\n   * Is locked\n   *\n   * @return {boolean} True if locked and can't be deleted, false if not locked\n   */\n  get locked() {\n    return Boolean(this.attributes.get('locked'));\n  }\n\n  /**\n   * Get app data\n   *\n   * @return {Object} App data\n   */\n  get appData() {\n    return this.attributes.get('appdata');\n  }\n\n  /**\n   * Set app data\n   *\n   * @param {Object} data App data\n   */\n  set appData(data) {\n    this.attributes.set('appdata', Object.assign({}, data));\n  }\n\n  /**\n   * Get picture\n   *\n   * @return {string} Picture (reserved value)\n   */\n  get picture() {\n    return this.attributes.get('picture');\n  }\n\n  /**\n   * Get last updated\n   *\n   * @return {string} Last updated\n   */\n  get lastUpdated() {\n    return this.attributes.get('lastupdated');\n  }\n\n  /**\n   * Get version\n   *\n   * @return {int} Version\n   */\n  get version() {\n    return this.attributes.get('version');\n  }\n\n  /**\n   * Get capture light state\n   *\n   * @return {null} Null\n   */\n  get captureLightState() {\n    return null;\n  }\n\n  /**\n   * Set capture current light state\n   *\n   * @param {boolean} capture True to capture, false to not\n   */\n  set captureLightState(capture) {\n    this.attributes.set('storelightstate', Boolean(capture));\n  }\n\n  /**\n   * Get light state\n   *\n   * @param {string} lightId Light Id\n   *\n   * @return {mixed} Light state object, or undefined\n   */\n  getLightState(lightId) {\n    return this.lightStates.get(String(lightId));\n  }\n\n  /**\n   * Set light state\n   *\n   * @param {string} lightId Light Id\n   * @param {Object} state   State\n   */\n  setLightState(lightId, state) {\n    this.lightStates.set(String(lightId), state);\n  }\n\n  /**\n   * Get transition time\n   *\n   * @return {null} Null\n   */\n  get transitionTime() {\n    return null;\n  }\n\n  /**\n   * Set transition time\n   *\n   * @param {int} time Time in seconds\n   */\n  set transitionTime(time) {\n    this.attributes.set('transitiontime', Number(time) * 10);\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Id\n   */\n  toString() {\n    return this.id;\n  }\n}\n\nmodule.exports = Scene;\n"
  },
  {
    "path": "lib/Model/Schedule.js",
    "content": "'use strict';\n\nlet Attributes     = require('./Attributes');\nlet AbstractAction = require('../Action/AbstractAction');\n\nconst DEFAULT_ATTRIBUTES = {\n  'status':    'enabled',\n  'autodelete': true,\n};\n\n/**\n * Schedule\n *\n * Schedule object\n */\nclass Schedule {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes Attributes\n   */\n  constructor(attributes) {\n    this.attributes = new Attributes(attributes, DEFAULT_ATTRIBUTES);\n  }\n\n  /**\n   * Get schedule id\n   *\n   * @return {string} Schedule id\n   */\n  get id() {\n    return this.attributes.get('id');\n  }\n\n  /**\n   * Get name\n   *\n   * @return {string} Name\n   */\n  get name() {\n    return this.attributes.get('name');\n  }\n\n  /**\n   * Set name\n   *\n   * @param {string} name Name\n   */\n  set name(name) {\n    this.attributes.set('name', String(name));\n  }\n\n  /**\n   * Get description\n   *\n   * @return {string} Description\n   */\n  get description() {\n    return this.attributes.get('description');\n  }\n\n  /**\n   * Set description\n   *\n   * @param {string} description Description\n   */\n  set description(description) {\n    this.attributes.set('description', String(description));\n  }\n\n  /**\n   * Get action\n   *\n   * @return {Object} Action\n   */\n  get action() {\n    return this.attributes.get('command');\n  }\n\n  /**\n   * Set action\n   *\n   * @param {Object} action Action\n   */\n  set action(action) {\n    if (!(action instanceof AbstractAction)) {\n      throw new Error({\n        message: 'Expecting Action'\n      });\n    }\n\n    this.attributes.set('command', action);\n  }\n\n  /**\n   * Get created time\n   *\n   * @return {string} Created time\n   */\n  get created() {\n    return this.attributes.get('created');\n  }\n\n  /**\n   * Get status\n   *\n   * @return {string} Status\n   */\n  get status() {\n    return String(this.attributes.get('status'));\n  }\n\n  /**\n   * Set status\n   *\n   * @param {string} value Value\n   */\n  set status(value) {\n    value = (value === 'enabled')\n      ? 'enabled'\n      : 'disabled';\n\n    this.attributes.set('status', value);\n  }\n\n  /**\n   * Get auto delete\n   *\n   * @return {bool} True to auto delete, false if not\n   */\n  get autoDelete() {\n    return Boolean(this.attributes.get('autodelete'));\n  }\n\n  /**\n   * Set auto delete\n   *\n   * @param {bool} value True to auto delete, false if not\n   */\n  set autoDelete(value) {\n    this.attributes.set('autodelete', Boolean(value));\n  }\n\n  /**\n   * Get local time (when schedule fires)\n   *\n   * @return {string} Local time\n   */\n  get localTime() {\n    return String(this.attributes.get('localtime'));\n  }\n\n  /**\n   * Set local time\n   *\n   * @param {mixed} date Custom date, or time pattern\n   */\n  set localTime(date) {\n    this.attributes.set('localtime', String(date));\n  }\n\n  /**\n   * Get start time\n   *\n   * @return {string} Start time\n   */\n  get startTime() {\n    return this.attributes.get('starttime');\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Id\n   */\n  toString() {\n    return this.id;\n  }\n}\n\nmodule.exports = Schedule;\n"
  },
  {
    "path": "lib/Model/Sensor.js",
    "content": "'use strict';\n\nlet Attributes         = require('./Attributes');\nlet SensorModelFactory = require('../SensorModel/Factory');\nlet SensorTypeFactory  = require('../SensorType/Factory');\n\nconst DEFAULT_ATTRIBUTES = {\n  'type': 'CLIPGenericStatus',\n};\n\n/**\n * Sensor\n *\n * Sensor object\n */\nclass Sensor {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes Attributes\n   * @param {Object} config     Config\n   * @param {Object} state      State\n   */\n  constructor(attributes, config, state) {\n    this.attributes = new Attributes(attributes, DEFAULT_ATTRIBUTES);\n\n    this.reloadConfigAndState(config, state);\n  }\n\n  /**\n   * Get Id\n   *\n   * @return {string} Id\n   */\n  get id() {\n    return this.attributes.get('id');\n  }\n\n  /**\n   * Get name\n   *\n   * @return {string} Name\n   */\n  get name() {\n    return this.attributes.get('name');\n  }\n\n  /**\n   * Set name\n   *\n   * @param {string} name Name\n   */\n  set name(name) {\n    this.attributes.set('name', String(name));\n  }\n\n  /**\n   * Get type\n   *\n   * @return {string} Type\n   */\n  get type() {\n    return this.attributes.get('type');\n  }\n\n  /**\n   * Set type\n   *\n   * @param {string} type Type\n   */\n  set type(type) {\n    this.attributes.set('type', String(type));\n\n    this.reloadConfigAndState(\n      this.config.attributes.getAll(),\n      this.state.attributes.getAll()\n    );\n  }\n\n  /**\n   * Get model id\n   *\n   * @return {string} Model Id\n   */\n  get modelId() {\n    return this.attributes.get('modelid');\n  }\n\n  /**\n   * Set model id\n   *\n   * @param {string} modelId Model Id\n   */\n  set modelId(modelId) {\n    this.attributes.set('modelid', String(modelId));\n\n    delete this.sensorModel;\n  }\n\n  /**\n   * Get model\n   *\n   * Lazy loads model for the sensor\n   *\n   * @return {SensorModel} Sensor model\n   */\n  get model() {\n    if (this.sensorModel === undefined) {\n      this.sensorModel = SensorModelFactory.createSensorModel(this.modelId);\n    }\n\n    return this.sensorModel;\n  }\n\n  /**\n   * Get manufacturer\n   *\n   * @return {string} Manufacturer\n   */\n  get manufacturer() {\n    return this.attributes.get('manufacturername');\n  }\n\n  /**\n   * Set manufacturer\n   *\n   * @param {string} manufacturer Manufacturer\n   */\n  set manufacturer(manufacturer) {\n    this.attributes.set('manufacturername', String(manufacturer));\n  }\n\n  /**\n   * Get product id\n   *\n   * @return {string} Product Id\n   */\n  get productId() {\n    return this.attributes.get('productid');\n  }\n\n  /**\n   * Get software version\n   *\n   * @return {string} Software version\n   */\n  get softwareVersion() {\n    return this.attributes.get('swversion');\n  }\n\n  /**\n   * Set software version\n   *\n   * @param {string} softwareVersion Software version\n   */\n  set softwareVersion(softwareVersion) {\n    this.attributes.set('swversion', String(softwareVersion));\n  }\n\n  /**\n   * Get software config id\n   *\n   * @return {string} Software config id\n   */\n  get softwareConfigId() {\n    return this.attributes.get('swconfigid');\n  }\n\n  /**\n   * Get unique Id\n   *\n   * @return {string} Unique Id\n   */\n  get uniqueId() {\n    return this.attributes.get('uniqueid');\n  }\n\n  /**\n   * Set unique Id\n   *\n   * @param {string} uniqueId Unique Id\n   */\n  set uniqueId(uniqueId) {\n    this.attributes.set('uniqueid', String(uniqueId));\n  }\n\n  /**\n   * Reload config and state\n   *\n   * @param {Object} config Config\n   * @param {Object} state  State\n   */\n  reloadConfigAndState(config, state) {\n    this.config = SensorTypeFactory.createSensorConfig(this.type, config);\n    this.state  = SensorTypeFactory.createSensorState(this.type, state);\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Id\n   */\n  toString() {\n    return this.id;\n  }\n}\n\nmodule.exports = Sensor;\n"
  },
  {
    "path": "lib/Model/SoftwareUpdate.js",
    "content": "'use strict';\n\nlet Attributes = require('./Attributes');\n\nconst UPDATE_STATE_MAP = {\n  0: 'NO_UPDATE',\n  1: 'DOWNLOADING',\n  2: 'READY_TO_INSTALL',\n  3: 'INSTALLING',\n}\n\n/**\n * Software update object\n *\n * Software update details\n */\nclass SoftwareUpdate {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes Attributes\n   */\n  constructor(attributes) {\n    this.attributes = new Attributes(attributes);\n  }\n\n  /**\n   * Get state\n   *\n   * @return {string} Update state\n   */\n  get state() {\n    return UPDATE_STATE_MAP[this.attributes.get('updatestate')];\n  }\n\n  /**\n   * Is checking for update\n   *\n   * @return {Boolean} True if checking for update, false if not\n   */\n  get checkingEnabled() {\n    return Boolean(this.attributes.get('checkforupdate'));\n  }\n\n  /**\n   * Is bridge updatable\n   *\n   * @return {Boolean} Is bridge updatable\n   */\n  get bridge() {\n    return Boolean(this.attributes.get('devicetypes').bridge);\n  }\n\n  /**\n   * Get updatable lights\n   *\n   * @return {array} List of updatable lights\n   */\n  get lights() {\n    return this.attributes.get('devicetypes').lights;\n  }\n\n  /**\n   * Get updatable sensors\n   *\n   * @return {array} List of updatable sensors\n   */\n  get sensors() {\n    return this.attributes.get('devicetypes').sensors;\n  }\n\n  /**\n   * Get release url\n   *\n   * @return {string} Release url\n   */\n  get releaseUrl() {\n    return this.attributes.get('url');\n  }\n\n  /**\n   * Get release notes\n   *\n   * @return {string} Release notes\n   */\n  get releaseNotes() {\n    return this.attributes.get('text');\n  }\n\n  /**\n   * Is install notification enabled\n   *\n   * @return {Boolean} True if enabled, false if not\n   */\n  get installNotificationEnabled() {\n    return Boolean(this.attributes.get('notify'));\n  }\n}\n\nmodule.exports = SoftwareUpdate;\n"
  },
  {
    "path": "lib/Model/User.js",
    "content": "'use strict';\n\nlet Attributes = require('./Attributes');\n\nconst DEFAULT_ATTRIBUTES = {\n  name: 'huejay'\n};\n\n/**\n * User\n *\n * User object\n */\nclass User {\n  /**\n   * Constructor\n   *\n   * @param {Object} attributes Attributes\n   */\n  constructor(attributes) {\n    this.attributes = new Attributes(attributes, DEFAULT_ATTRIBUTES);\n  }\n\n  /**\n   * Get username\n   *\n   * @return {string} Username\n   */\n  get username() {\n    return this.attributes.get('username');\n  }\n\n  /**\n   * Get device type\n   *\n   * @return {string} Device type\n   */\n  get deviceType() {\n    return this.attributes.get('name');\n  }\n\n  /**\n   * Set device type\n   *\n   * @param {string} type Type\n   */\n  set deviceType(type) {\n    return this.attributes.set('name', type);\n  }\n\n  /**\n   * Get create date\n   *\n   * @return {string} Create date\n   */\n  get created() {\n    return this.attributes.get('create date');\n  }\n\n  /**\n   * Get last use date\n   *\n   * @return {string} Date\n   */\n  get lastUsed() {\n    return this.attributes.get('last use date');\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Username\n   */\n  toString() {\n    return this.username;\n  }\n}\n\nmodule.exports = User;\n"
  },
  {
    "path": "lib/SensorModel/AbstractSensorModel.js",
    "content": "'use strict';\n\n/**\n * Abstract sensor model\n */\nclass AbstractSensorModel {\n  /**\n   * Constructor\n   *\n   * @param {Object} details Sensor model details\n   */\n  constructor(details) {\n    this.details = Object.assign({}, details);\n  }\n\n  /**\n   * Get id of model\n   *\n   * @return {string} Id\n   */\n  get id() {\n    return this.details.id;\n  }\n\n  /**\n   * Get manufacturer\n   *\n   * @return {string} Manufacturer\n   */\n  get manufacturer() {\n    return this.details.manufacturer;\n  }\n\n  /**\n   * Get name of model\n   *\n   * @return {string} Name\n   */\n  get name() {\n    return this.details.name;\n  }\n\n  /**\n   * Get type\n   *\n   * @return {string} Type\n   */\n  get type() {\n    return this.details.type;\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Name\n   */\n  toString() {\n    return this.name;\n  }\n}\n\nmodule.exports = AbstractSensorModel;\n"
  },
  {
    "path": "lib/SensorModel/Factory.js",
    "content": "'use strict';\n\n/**\n * Factory for Sensor Models\n */\nclass Factory {\n  /**\n   * Create sensor model\n   *\n   * @param {string} modelId Model Id\n   *\n   * @return {AbstractSensorModel} Sensor model\n   */\n  static createSensorModel(modelId) {\n    let SensorModel = null;\n\n    try {\n      SensorModel = require(`./${modelId}`);\n    } catch (e) {\n      SensorModel = require(`./Unknown`);\n    }\n\n    return new SensorModel;\n  }\n}\n\nmodule.exports = Factory;\n"
  },
  {
    "path": "lib/SensorModel/PHDL00.js",
    "content": "'use strict';\n\nlet AbstractSensorModel = require('./AbstractSensorModel');\n\nconst DETAILS = {\n  id:           'PHDL00',\n  manufacturer: 'Philips',\n  name:         'Hue Daylight Sensor',\n  type:         'Daylight',\n};\n\n/**\n * Sensor model: PHDL00\n */\nclass PHDL00 extends AbstractSensorModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = PHDL00;\n"
  },
  {
    "path": "lib/SensorModel/RWL020.js",
    "content": "'use strict';\n\nlet AbstractSensorModel = require('./AbstractSensorModel');\n\nconst DETAILS = {\n  id:           'RWL020',\n  manufacturer: 'Philips',\n  name:         'Hue Wireless Dimmer Switch',\n  type:         'ZLLSwitch',\n};\n\n/**\n * Sensor model: RWL020\n */\nclass RWL020 extends AbstractSensorModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = RWL020;\n"
  },
  {
    "path": "lib/SensorModel/RWL021.js",
    "content": "'use strict';\n\nlet AbstractSensorModel = require('./AbstractSensorModel');\n\nconst DETAILS = {\n  id:           'RWL021',\n  manufacturer: 'Philips',\n  name:         'Hue Wireless Dimmer Switch',\n  type:         'ZLLSwitch',\n};\n\n/**\n * Sensor model: RWL021\n */\nclass RWL021 extends AbstractSensorModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = RWL021;\n"
  },
  {
    "path": "lib/SensorModel/SML001.js",
    "content": "'use strict';\n\nlet AbstractSensorModel = require('./AbstractSensorModel');\n\nconst DETAILS = {\n  id:           'SML001',\n  manufacturer: 'Philips',\n  name:         'Hue Motion Sensor',\n  type:         'ZLLPresence',\n};\n\n/**\n * Sensor model: SML001\n */\nclass SML001 extends AbstractSensorModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = SML001;\n"
  },
  {
    "path": "lib/SensorModel/Unknown.js",
    "content": "'use strict';\n\nlet AbstractSensorModel = require('./AbstractSensorModel');\n\nconst DETAILS = {\n  id:           null,\n  manufacturer: null,\n  name:         null,\n  type:         null,\n};\n\n/**\n * Sensor model: Unknown\n */\nclass Unknown extends AbstractSensorModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = Unknown;\n"
  },
  {
    "path": "lib/SensorModel/ZGPSWITCH.js",
    "content": "'use strict';\n\nlet AbstractSensorModel = require('./AbstractSensorModel');\n\nconst DETAILS = {\n  id:           'ZGPSWITCH',\n  manufacturer: 'Philips',\n  name:         'Hue Tap',\n  type:         'ZGPSwitch',\n};\n\n/**\n * Sensor model: ZGPSWITCH\n */\nclass ZGPSWITCH extends AbstractSensorModel {\n  /**\n   * Constructor\n   */\n  constructor() {\n    super(DETAILS);\n  }\n}\n\nmodule.exports = ZGPSWITCH;\n"
  },
  {
    "path": "lib/SensorType/AbstractClipSensorConfig.js",
    "content": "'use strict';\n\nlet AbstractSensorConfig = require('./AbstractSensorConfig');\n\n/**\n * Abstract clip sensor config\n */\nclass AbstractClipSensorConfig extends AbstractSensorConfig {\n  /**\n   * Get reachable\n   *\n   * @return {bool} True if reachable, false if not\n   */\n  get reachable() {\n    return this.attributes.get('reachable');\n  }\n\n  /**\n   * Get battery level\n   *\n   * @return {int} Battery level\n   */\n  get battery() {\n    return this.attributes.get('battery');\n  }\n\n  /**\n   * Set battery level\n   *\n   * @param {int} level Level\n   */\n  set battery(level) {\n    this.attributes.set('battery', parseInt(level, 10));\n  }\n\n  /**\n   * Get URL\n   *\n   * @return {string} URL\n   */\n  get url() {\n    return this.attributes.get('url');\n  }\n\n  /**\n   * Set URL\n   *\n   * @param {string} url URL\n   */\n  set url(url) {\n    this.attributes.set('url', String(url));\n  }\n}\n\nmodule.exports = AbstractClipSensorConfig;\n"
  },
  {
    "path": "lib/SensorType/AbstractSensorConfig.js",
    "content": "'use strict';\n\nlet Attributes = require('../Model/Attributes');\n\n/**\n * Abstract sensor config\n */\nclass AbstractSensorConfig {\n  /**\n   * Constructor\n   *\n   * @param {Object} config Config\n   */\n  constructor(config) {\n    this.attributes = new Attributes(config);\n  }\n\n  /**\n   * Get on\n   *\n   * @return {bool} True if on, false if not\n   */\n  get on() {\n    return this.attributes.get('on');\n  }\n\n  /**\n   * Set on\n   *\n   * @param {bool} value True if on, false if not\n   */\n  set on(value) {\n    this.attributes.set('on', Boolean(value));\n  }\n}\n\nmodule.exports = AbstractSensorConfig;\n"
  },
  {
    "path": "lib/SensorType/AbstractSensorState.js",
    "content": "'use strict';\n\nlet Attributes = require('../Model/Attributes');\n\n/**\n * Abstract sensor state\n */\nclass AbstractSensorState {\n  /**\n   * Constructor\n   *\n   * @param {Object} state State\n   */\n  constructor(state) {\n    this.attributes = new Attributes(state);\n  }\n\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return {\n      lastUpdated: 'lastupdated'\n    };\n  }\n\n  /**\n   * Get last updated\n   *\n   * @return {string} Last updated\n   */\n  get lastUpdated() {\n    return this.attributes.get('lastupdated') !== 'none'\n      ? this.attributes.get('lastupdated')\n      : null;\n  }\n}\n\nmodule.exports = AbstractSensorState;\n"
  },
  {
    "path": "lib/SensorType/AbstractZLLSensorConfig.js",
    "content": "'use strict';\n\nlet AbstractSensorConfig = require('./AbstractSensorConfig');\n\n/**\n * Abstract ZLL sensor config\n */\nclass AbstractZLLSensorConfig extends AbstractSensorConfig {\n  /**\n   * Get reachable\n   *\n   * @return {bool} True if reachable, false if not\n   */\n  get reachable() {\n    return this.attributes.get('reachable');\n  }\n\n  /**\n   * Get battery level\n   *\n   * @return {int} Battery level\n   */\n  get battery() {\n    return this.attributes.get('battery');\n  }\n\n  /**\n   * Get alert\n   *\n   * @return {string} Alert value\n   */\n  get alert() {\n    return this.attributes.get('alert');\n  }\n\n  /**\n   * Set alert\n   *\n   * @param {bool} value Alert value\n   */\n  set alert(value) {\n    this.attributes.set('alert', value);\n  }\n\n  /**\n   * Is user test?\n   *\n   * @return {bool} True if user test mode, false if not\n   */\n  get userTest() {\n    return this.attributes.get('usertest');\n  }\n\n  /**\n   * Set user test\n   *\n   * @param {bool} value True or false\n   */\n  set userTest(value) {\n    this.attributes.set('usertest', Boolean(value));\n  }\n\n  /**\n   * Get pending config\n   *\n   * @return {array} List of configs pending change on device\n   */\n  get pending() {\n    return this.attributes.get('pending');\n  }\n\n  /**\n   * LED indication?\n   *\n   * @return {bool} True if LED indication, false if not\n   */\n  get ledIndication() {\n    return this.attributes.get('ledindication');\n  }\n\n  /**\n   * Set LED indication\n   *\n   * @param {bool} value True or false\n   */\n  set ledIndication(value) {\n    this.attributes.set('ledindication', Boolean(value));\n  }\n}\n\nmodule.exports = AbstractZLLSensorConfig;\n"
  },
  {
    "path": "lib/SensorType/CLIPGenericFlag/Config.js",
    "content": "'use strict';\n\nlet AbstractClipSensorConfig = require('../AbstractClipSensorConfig');\n\n/**\n * CLIPGenericFlag sensor: Config\n */\nclass Config extends AbstractClipSensorConfig {}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/CLIPGenericFlag/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * CLIPGenericFlag sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      flag: 'flag'\n    });\n  }\n\n  /**\n   * Get flag\n   *\n   * @return {bool} True or false\n   */\n  get flag() {\n    return this.attributes.get('flag');\n  }\n\n  /**\n   * Set flag\n   *\n   * @param {bool} value True or false\n   */\n  set flag(value) {\n    this.attributes.set('flag', Boolean(value));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/CLIPGenericStatus/Config.js",
    "content": "'use strict';\n\nlet AbstractClipSensorConfig = require('../AbstractClipSensorConfig');\n\n/**\n * CLIPGenericStatus sensor: Config\n */\nclass Config extends AbstractClipSensorConfig {}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/CLIPGenericStatus/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * CLIPGenericStatus sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      status: 'status'\n    });\n  }\n\n  /**\n   * Get status\n   *\n   * @return {int} Number\n   */\n  get status() {\n    return this.attributes.get('status');\n  }\n\n  /**\n   * Set status\n   *\n   * @param {int} value Number\n   */\n  set status(value) {\n    this.attributes.set('status', parseInt(value, 10));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/CLIPHumidity/Config.js",
    "content": "'use strict';\n\nlet AbstractClipSensorConfig = require('../AbstractClipSensorConfig');\n\n/**\n * CLIPHumidity sensor: Config\n */\nclass Config extends AbstractClipSensorConfig {}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/CLIPHumidity/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * CLIPHumidity sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      humidity: 'humidity'\n    });\n  }\n\n  /**\n   * Get humidity\n   *\n   * @return {float} Temperature (Celsius)\n   */\n  get humidity() {\n    return this.attributes.get('humidity') / 100;\n  }\n\n  /**\n   * Set humidity\n   *\n   * @param {float} degrees Degrees\n   */\n  set humidity(degrees) {\n    this.attributes.set('humidity', Math.round(Number(degrees) * 100));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/CLIPLightLevel/Config.js",
    "content": "'use strict';\n\nlet AbstractClipSensorConfig = require('../AbstractClipSensorConfig');\n\n/**\n * CLIPLightLevel sensor: Config\n */\nclass Config extends AbstractClipSensorConfig {\n  /**\n   * Get dark threshold\n   * \n   * @return {int} Dark threshold\n   */\n  get darkThreshold() {\n    return this.attributes.get('tholddark');\n  }\n\n  /**\n   * Set dark threshold\n   * \n   * @param {int} Threshold\n   */\n  set darkThreshold(threshold) {\n    this.attributes.set('tholddark', parseInt(threshold, 10));\n  }\n\n  /**\n   * Get threshold offset\n   * \n   * @return {int} Threshold offset\n   */\n  get thresholdOffset() {\n    return this.attributes.get('tholdoffset');\n  }\n\n  /**\n   * Set threshold offset\n   * \n   * @param {int} Threshold\n   */\n  set thresholdOffest(threshold) {\n    this.attributes.set('tholdoffset', parseInt(threshold, 10));\n  }\n}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/CLIPLightLevel/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * CLIPLightLevel sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      lightLevel: 'lightlevel',\n      dark:       'dark',\n      daylight:   'daylight'\n    });\n  }\n\n  /**\n   * Get light level\n   *\n   * @return {int} Light level\n   */\n  get lightLevel() {\n    return this.attributes.get('lightlevel');\n  }\n\n  /**\n   * Get dark stats\n   *\n   * @return {int} Is dark?\n   */\n  get dark() {\n    return Boolean(this.attributes.get('dark'));\n  }\n\n  /**\n   * Get daylight status\n   *\n   * @return {bool} Is daylight?\n   */\n  get daylight() {\n    return Boolean(this.attributes.get('daylight'));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/CLIPOpenClose/Config.js",
    "content": "'use strict';\n\nlet AbstractClipSensorConfig = require('../AbstractClipSensorConfig');\n\n/**\n * CLIPOpenClose sensor: Config\n */\nclass Config extends AbstractClipSensorConfig {}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/CLIPOpenClose/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * CLIPOpenClose sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      open: 'open'\n    });\n  }\n\n  /**\n   * Get open\n   *\n   * @return {bool} True or false\n   */\n  get open() {\n    return this.attributes.get('open');\n  }\n\n  /**\n   * Set open\n   *\n   * @param {bool} value True or false\n   */\n  set open(value) {\n    this.attributes.set('open', Boolean(value));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/CLIPPresence/Config.js",
    "content": "'use strict';\n\nlet AbstractClipSensorConfig = require('../AbstractClipSensorConfig');\n\n/**\n * CLIPPresence sensor: Config\n */\nclass Config extends AbstractClipSensorConfig {}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/CLIPPresence/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * CLIPPresence sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      presence: 'presence'\n    });\n  }\n\n  /**\n   * Get presence\n   *\n   * @return {bool} True or false\n   */\n  get presence() {\n    return this.attributes.get('presence');\n  }\n\n  /**\n   * Set presence\n   *\n   * @param {bool} value True or false\n   */\n  set presence(value) {\n    this.attributes.set('presence', Boolean(value));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/CLIPSwitch/Config.js",
    "content": "'use strict';\n\nlet AbstractClipSensorConfig = require('../AbstractClipSensorConfig');\n\n/**\n * CLIPSwitch sensor: Config\n */\nclass Config extends AbstractClipSensorConfig {}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/CLIPSwitch/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * CLIPSwitch sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      buttonEvent: 'buttonevent'\n    });\n  }\n\n  /**\n   * Get button event\n   *\n   * @return {int} Button event\n   */\n  get buttonEvent() {\n    return this.attributes.get('buttonevent');\n  }\n\n  /**\n   * Set button event\n   *\n   * @param {int} event Button event\n   */\n  set buttonEvent(event) {\n    this.attributes.set('buttonevent', parseInt(event, 10));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/CLIPTemperature/Config.js",
    "content": "'use strict';\n\nlet AbstractClipSensorConfig = require('../AbstractClipSensorConfig');\n\n/**\n * CLIPTemperature sensor: Config\n */\nclass Config extends AbstractClipSensorConfig {}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/CLIPTemperature/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * CLIPTemperature sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      temperature: 'temperature'\n    });\n  }\n\n  /**\n   * Get temperature\n   *\n   * @return {float} Temperature (Celsius)\n   */\n  get temperature() {\n    return this.attributes.get('temperature') / 100;\n  }\n\n  /**\n   * Set temperature\n   *\n   * @param {float} degrees Degrees\n   */\n  set temperature(degrees) {\n    this.attributes.set('temperature', Math.round(Number(degrees) * 100));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/Daylight/Config.js",
    "content": "'use strict';\n\nlet AbstractSensorConfig = require('../AbstractSensorConfig');\n\n/**\n * Daylight sensor: Config\n */\nclass Config extends AbstractSensorConfig {\n  /**\n   * Get longitude\n   *\n   * @return {string} Longitude\n   */\n  get longitude() {\n    return this.attributes.get('long');\n  }\n\n  /**\n   * Set longitude\n   *\n   * @param {string} value Longitude\n   */\n  set longitude(value) {\n    this.attributes.set('long', String(value));\n  }\n\n  /**\n   * Get latitude\n   *\n   * @return {string} Latitude\n   */\n  get latitude() {\n    return this.attributes.get('lat');\n  }\n\n  /**\n   * Set latitude\n   *\n   * @param {string} value Latitude\n   */\n  set latitude(value) {\n    this.attributes.set('lat', String(value));\n  }\n\n  /**\n   * Is configured?\n   */\n  get configured() {\n    return this.attributes.get('configured');\n  }\n\n  /**\n   * Get sunrise offset (minutes)\n   */\n  get sunriseOffset() {\n    return this.attributes.get('sunriseoffset');\n  }\n\n  /**\n   * Set sunrise offset (minutes)\n   *\n   * @param {int} offset Offset in minutes\n   */\n  set sunriseOffset(offset) {\n    this.attributes.set('sunriseoffset', parseInt(offset, 10));\n  }\n\n  /**\n   * Get sunset offset (minutes)\n   */\n  get sunsetOffset() {\n    return this.attributes.get('sunsetoffset');\n  }\n\n  /**\n   * Get sunset offset (minutes)\n   *\n   * @param {int} offset Offset in minutes\n   */\n  set sunsetOffset(offset) {\n    this.attributes.set('sunsetoffset', parseInt(offset, 10));\n  }\n}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/Daylight/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * Daylight sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      daylight: 'daylight'\n    });\n  }\n\n  /**\n   * Get daylight\n   *\n   * @return {bool} True if daylight, false if not\n   */\n  get daylight() {\n    return this.attributes.get('daylight');\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/Factory.js",
    "content": "'use strict';\n\n/**\n * Factory for Sensor Types\n */\nclass Factory {\n  /**\n   * Create sensor config\n   *\n   * @param {string} type   Type\n   * @param {Object} config Config\n   *\n   * @return {Object} Sensor config\n   */\n  static createSensorConfig(type, config) {\n    let SensorConfig = this.mapSensorType(type, 'Config');\n\n    return new SensorConfig(config);\n  }\n\n  /**\n   * Create sensor state\n   *\n   * @param {string} type  Type\n   * @param {Object} state State\n   *\n   * @return {Object} Sensor state\n   */\n  static createSensorState(type, state) {\n    let SensorState = this.mapSensorType(type, 'State');\n\n    return new SensorState(state);\n  }\n\n  /**\n   * Map sensor type\n   *\n   * @param {string} type Type\n   *\n   * @return {string} Type\n   */\n  static mapSensorType(type, resource) {\n    let SensorResource = null;\n\n    try {\n      SensorResource = require(`./${type}/${resource}`);\n    } catch (e) {\n      SensorResource = require(`./Unknown/${resource}`);\n    }\n\n    return SensorResource;\n  }\n}\n\nmodule.exports = Factory;\n"
  },
  {
    "path": "lib/SensorType/Unknown/Config.js",
    "content": "'use strict';\n\nlet AbstractSensorConfig = require('../AbstractSensorConfig');\n\n/**\n * Unknown sensor: Config\n */\nclass Config extends AbstractSensorConfig {}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/Unknown/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * Unknown sensor: State\n */\nclass State extends AbstractSensorState {}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/ZGPSwitch/Config.js",
    "content": "'use strict';\n\nlet AbstractSensorConfig = require('../AbstractSensorConfig');\n\n/**\n * ZGPSwitch sensor: Config\n */\nclass Config extends AbstractSensorConfig {}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/ZGPSwitch/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * ZGPSwitch sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      buttonEvent: 'buttonevent'\n    });\n  }\n\n  /**\n   * Get button event\n   *\n   * @return {int} Button event\n   */\n  get buttonEvent() {\n    return this.attributes.get('buttonevent');\n  }\n\n  /**\n   * Set button event\n   *\n   * @param {int} event Button event\n   */\n  set buttonEvent(event) {\n    this.attributes.set('buttonevent', parseInt(event, 10));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/ZLLLightLevel/Config.js",
    "content": "'use strict';\n\nlet AbstractZLLSensorConfig = require('../AbstractZLLSensorConfig');\n\n/**\n * ZLLLightLevel sensor: Config\n */\nclass Config extends AbstractZLLSensorConfig {\n  /**\n   * Get dark threshold\n   *\n   * @return {int} Dark threshold\n   */\n  get darkThreshold() {\n    return this.attributes.get('tholddark');\n  }\n\n  /**\n   * Set dark threshold\n   *\n   * @param {int} Threshold\n   */\n  set darkThreshold(threshold) {\n    this.attributes.set('tholddark', parseInt(threshold, 10));\n  }\n\n  /**\n   * Get threshold offset\n   *\n   * @return {int} Threshold offset\n   */\n  get thresholdOffset() {\n    return this.attributes.get('tholdoffset');\n  }\n\n  /**\n   * Set threshold offset\n   *\n   * @param {int} Threshold\n   */\n  set thresholdOffest(threshold) {\n    this.attributes.set('tholdoffset', parseInt(threshold, 10));\n  }\n}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/ZLLLightLevel/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * ZLLLightLevel sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      lightLevel: 'lightlevel',\n      dark:       'dark',\n      daylight:   'daylight'\n    });\n  }\n\n  /**\n   * Get light level\n   *\n   * @return {int} Light level\n   */\n  get lightLevel() {\n    return this.attributes.get('lightlevel');\n  }\n\n  /**\n   * Get dark stats\n   *\n   * @return {int} Is dark?\n   */\n  get dark() {\n    return Boolean(this.attributes.get('dark'));\n  }\n\n  /**\n   * Get daylight status\n   *\n   * @return {bool} Is daylight?\n   */\n  get daylight() {\n    return Boolean(this.attributes.get('daylight'));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/ZLLPresence/Config.js",
    "content": "'use strict';\n\nlet AbstractZLLSensorConfig = require('../AbstractZLLSensorConfig');\n\n/**\n * ZLLPresence sensor: Config\n */\nclass Config extends AbstractZLLSensorConfig {\n  /**\n   * Get sensitivity\n   *\n   * @return {int} Sensitivity\n   */\n  get sensitivity() {\n    return this.attributes.get('sensitivity');\n  }\n\n  /**\n   * Get max sensitivity\n   *\n   * @return {int} Max sensitivity\n   */\n  get maxSensitivity() {\n    return this.attributes.get('sensitivitymax');\n  }\n}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/ZLLPresence/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * ZLLPresence sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      presence: 'presence'\n    });\n  }\n\n  /**\n   * Get presence\n   *\n   * @return {bool} True or false\n   */\n  get presence() {\n    return this.attributes.get('presence');\n  }\n\n  /**\n   * Set presence\n   *\n   * @param {bool} value True or false\n   */\n  set presence(value) {\n    this.attributes.set('presence', Boolean(value));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/ZLLSwitch/Config.js",
    "content": "'use strict';\n\nlet AbstractZLLSensorConfig = require('../AbstractZLLSensorConfig');\n\n/**\n * ZLLSwitch sensor: Config\n */\nclass Config extends AbstractZLLSensorConfig {}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/ZLLSwitch/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * ZLLSwitch sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      buttonEvent: 'buttonevent'\n    });\n  }\n\n  /**\n   * Get button event\n   *\n   * @return {int} Button event\n   */\n  get buttonEvent() {\n    return this.attributes.get('buttonevent');\n  }\n\n  /**\n   * Set button event\n   *\n   * @param {int} event Button event\n   */\n  set buttonEvent(event) {\n    this.attributes.set('buttonevent', parseInt(event, 10));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/SensorType/ZLLTemperature/Config.js",
    "content": "'use strict';\n\nlet AbstractZLLSensorConfig = require('../AbstractZLLSensorConfig');\n\n/**\n * ZLLTemperature sensor: Config\n */\nclass Config extends AbstractZLLSensorConfig {}\n\nmodule.exports = Config;\n"
  },
  {
    "path": "lib/SensorType/ZLLTemperature/State.js",
    "content": "'use strict';\n\nlet AbstractSensorState = require('../AbstractSensorState');\n\n/**\n * ZLLTemperature sensor: State\n */\nclass State extends AbstractSensorState {\n  /**\n   * Get state map\n   *\n   * @return {Object} State map\n   */\n  get stateMap() {\n    return Object.assign(super.stateMap, {\n      temperature: 'temperature'\n    });\n  }\n\n  /**\n   * Get temperature\n   *\n   * @return {float} Temperature (Celsius)\n   */\n  get temperature() {\n    return this.attributes.get('temperature') / 100;\n  }\n\n  /**\n   * Set temperature\n   *\n   * @param {float} degrees Degrees\n   */\n  set temperature(degrees) {\n    this.attributes.set('temperature', Math.round(Number(degrees) * 100));\n  }\n}\n\nmodule.exports = State;\n"
  },
  {
    "path": "lib/TimePattern/AbsoluteTime.js",
    "content": "'use strict';\n\nlet moment  = require('moment');\n\n/**\n * Absolute time\n */\nclass AbsoluteTime {\n  /**\n   * Constructor\n   *\n   * @param {string} date Date\n   */\n  constructor(date) {\n    this.date = String(date);\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Formatted time for scheduling\n   */\n  toString() {\n    return moment(this.date).format('YYYY-MM-DD[T]HH:mm:ss');\n  }\n}\n\nmodule.exports = AbsoluteTime;\n"
  },
  {
    "path": "lib/TimePattern/RandomizedTime.js",
    "content": "'use strict';\n\nlet moment  = require('moment');\nlet sprintf = require('sprintf-js').sprintf;\n\n/**\n * Randomized time\n */\nclass RandomizedTime {\n  /**\n   * Constructor\n   *\n   * @param {string} date          Date\n   * @param {int}    withinSeconds Randomize within seconds\n   */\n  constructor(date, withinSeconds) {\n    this.date          = String(date);\n    this.withinSeconds = parseInt(withinSeconds, 10);\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Formatted time for scheduling\n   */\n  toString() {\n    let schedule = moment(this.date).format('YYYY-MM-DD\\THH:mm:ss');\n\n    let hours   = parseInt(this.withinSeconds / 3600, 10);\n    let minutes = parseInt(this.withinSeconds % 3600 / 60, 10);\n    let seconds = this.withinSeconds % 60;\n\n    schedule += sprintf('A%1$02d:%2$02d:%3$02d', hours, minutes, seconds);\n\n    return schedule;\n  }\n}\n\n\nmodule.exports = RandomizedTime;\n"
  },
  {
    "path": "lib/TimePattern/RecurringTime.js",
    "content": "'use strict';\n\nlet moment  = require('moment');\n\n/**\n * Recurring time\n */\nclass RecurringTime {\n  /**\n   * Constructor\n   *\n   * @param {int}    daysOfWeek Days of week\n   * @param {string} timeOfDay  Time of day\n   */\n  constructor(daysOfWeek, timeOfDay) {\n    this.daysOfWeek = parseInt(daysOfWeek, 10);\n\n    this.timeOfDay = moment(String(timeOfDay), 'HH:mm:ss').format('HH:mm:ss');\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Formatted time for scheduling\n   */\n  toString() {\n    return `W${this.daysOfWeek}/T${this.timeOfDay}`;\n  }\n}\n\n// Weekdays\nRecurringTime.MONDAY    = 64;\nRecurringTime.TUESDAY   = 32;\nRecurringTime.WEDNESDAY = 16;\nRecurringTime.THURSDAY  = 8;\nRecurringTime.FRIDAY    = 4;\nRecurringTime.SATURDAY  = 2;\nRecurringTime.SUNDAY    = 1;\n\n// Grouped days\nRecurringTime.WEEKDAY   = 124;\nRecurringTime.WEEKEND   = 3;\n\nmodule.exports = RecurringTime;\n"
  },
  {
    "path": "lib/TimePattern/Timer.js",
    "content": "'use strict';\n\nlet sprintf = require('sprintf-js').sprintf;\n\n/**\n * Timer\n */\nclass Timer {\n  /**\n   * Constructor\n   *\n   * @param {int}  seconds Seconds\n   * @param {bool} repeat  Repeat\n   */\n  constructor(seconds, repeat) {\n    this.seconds = parseInt(seconds, 10);\n    this.repeat  = repeat !== undefined ? parseInt(repeat, 10) : null;\n  }\n\n  /**\n   * To string\n   *\n   * @return {string} Formatted time for scheduling\n   */\n  toString() {\n    let hours   = parseInt(this.seconds / 3600, 10);\n    let minutes = parseInt(this.seconds % 3600 / 60, 10);\n    let seconds = this.seconds % 60;\n\n    let schedule = sprintf('PT%1$02d:%2$02d:%3$02d', hours, minutes, seconds);\n\n    if (this.repeat !== null) {\n      schedule = sprintf('R%1$02d/%2$s', this.repeat, schedule);\n    }\n\n    return schedule;\n  }\n}\n\nmodule.exports = Timer;\n"
  },
  {
    "path": "lib/Transport.js",
    "content": "'use strict';\n\nlet axios       = require('axios');\nlet path        = require('path');\nlet HuejayError = require('./Error');\n\n/**\n * Transport\n *\n * Response for making requests to Philips Hue API\n */\nclass Transport {\n  /**\n   * Constructor\n   *\n   * @param {Client} client Client\n   */\n  constructor(client) {\n    this.client = client;\n  }\n\n  /**\n   * Get HTTP client\n   *\n   * @return {mixed} Axios http client\n   */\n  getHttpClient() {\n    let httpClient = axios.create({\n      baseURL: `http://${this.client.host}:${this.client.port}/`,\n      headers: {\n        'Content-Type': 'application/json'\n      },\n      timeout: this.client.timeout,\n      transformRequest: [\n        (data) => {\n          return JSON.stringify(data);\n        }\n      ],\n      responseType: 'json',\n    });\n\n    return httpClient;\n  }\n\n  /**\n   * Send request\n   *\n   * @param {Object} options Options for request\n   *\n   * @return {Promise} Promise for chaining\n   */\n  sendRequest(options) {\n    return this.getHttpClient()\n      .request(options)\n      .then(response => {\n        let result = response.data;\n\n        // Return response data immediately if raw data is expected\n        if (!!options.raw) {\n          return result;\n        }\n\n        // Return multiple results if expected\n        if (!!options.multi) {\n          let results = {};\n\n          for (let i in result) {\n            if (result[i].error !== undefined) {\n              throw new HuejayError({\n                type:    result[i].error.type,\n                message: result[i].error.description,\n              });\n            }\n\n            Object.assign(results, result[i].success);\n          }\n\n          return results;\n        }\n\n        // Use first array index if available\n        if (result[0] !== undefined) {\n          result = result[0];\n        }\n\n        // Reject if an error is returned\n        if (result.error !== undefined) {\n          throw new HuejayError({\n            type:    result.error.type,\n            message: result.error.description,\n          });\n        }\n\n        // Narrow down to success if available\n        if (result.success !== undefined) {\n          result = result.success;\n        }\n\n        return result;\n      })\n      .catch(error => {\n        if (error instanceof HuejayError) {\n          throw error;\n        }\n\n        throw new HuejayError({\n          message: error.message\n        });\n      });\n  }\n}\n\nmodule.exports = Transport;\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"huejay\",\n  \"version\": \"1.9.0\",\n  \"description\": \"Philips Hue client for Node.js\",\n  \"keywords\": [\n    \"hue\",\n    \"philips\",\n    \"huejay\",\n    \"client\",\n    \"api\",\n    \"iot\"\n  ],\n  \"maintainers\": [\n    \"Michael Squires <sqmk@php.net>\"\n  ],\n  \"license\": \"MIT\",\n  \"repository\": \"sqmk/huejay\",\n  \"main\": \"lib/Huejay.js\",\n  \"files\": [\n    \"lib\"\n  ],\n  \"scripts\": {\n    \"test\": \"mocha\"\n  },\n  \"dependencies\": {\n    \"moment\": \"^2.24.0\",\n    \"axios\": \"^0.18.0\",\n    \"sprintf-js\": \"^1.1.2\"\n  },\n  \"devDependencies\": {\n    \"mocha\": \"^6.1.4\",\n    \"chai\": \"^4.2.0\",\n    \"chai-as-promised\": \"^7.1.1\",\n    \"sinon\": \"^7.3.2\",\n    \"mockery\": \"^2.1.0\"\n  }\n}\n"
  },
  {
    "path": "test/Discovery.spec.js",
    "content": "'use strict';\n\nlet expect    = require('chai').expect;\nlet Discovery = require('../lib/Discovery');\n\ndescribe('Discovery', () => {\n  beforeEach(() => {\n    this.discovery = new Discovery;\n  });\n\n  describe('constructor', () => {\n    it('should set options', () => {\n      expect(this.discovery).to.have.property('options');\n    });\n  });\n});\n"
  },
  {
    "path": "test/Huejay.spec.js",
    "content": "'use strict';\n\nlet expect = require('chai').expect;\nlet Huejay = require('../lib/Huejay');\n\ndescribe('Huejay', () => {\n  describe('version property', () => {\n    it('should be a string', () => {\n      expect(Huejay).to.have.property('version');\n      expect(Huejay.version).to.be.a('string');\n    });\n  });\n\n  describe('discover property', () => {\n    it('should be a function', () => {\n      expect(Huejay).to.have.property('discover');\n      expect(Huejay.discover).to.be.a('function');\n    });\n  });\n\n  describe('Client property', () => {\n    it('should be a function', () => {\n      expect(Huejay).to.have.property('Client');\n      expect(Huejay.Client).to.be.a('function');\n    });\n  });\n\n  describe('Error property', () => {\n    it('should be a function', () => {\n      expect(Huejay).to.have.property('Error');\n      expect(Huejay.Error).to.be.a('function');\n    });\n  });\n});\n"
  },
  {
    "path": "test/TimePattern/AbsoluteTime.spec.js",
    "content": "'use strict';\n\nlet expect       = require('chai').expect;\nlet AbsoluteTime = require('../../lib/TimePattern/AbsoluteTime');\n\ndescribe('TimePattern/AbsoluteTime', () => {\n  describe('constructor', () => {\n    it('should set arguments', () => {\n      let schedule = new AbsoluteTime('2016-03-13 19:24:01');\n\n      expect(schedule.date).to.equal('2016-03-13 19:24:01');\n    });\n  });\n\n  describe('toString', () => {\n    it('should be expected format', () => {\n      let schedule = new AbsoluteTime('2016-03-13 19:24:01');\n\n      expect(String(schedule)).to.equal('2016-03-13T19:24:01');\n    });\n  });\n});\n"
  },
  {
    "path": "test/TimePattern/RandomizedTime.spec.js",
    "content": "'use strict';\n\nlet expect         = require('chai').expect;\nlet RandomizedTime = require('../../lib/TimePattern/RandomizedTime');\n\ndescribe('TimePattern/RandomizedTime', () => {\n  describe('constructor', () => {\n    it('should set arguments', () => {\n      let schedule = new RandomizedTime('2015-01-02 13:05:20', 12318);\n\n      expect(schedule.date).to.equal('2015-01-02 13:05:20');\n      expect(schedule.withinSeconds).to.equal(12318);\n    });\n  });\n\n  describe('toString', () => {\n    it('should be expected format', () => {\n      let schedule = new RandomizedTime('2015-01-02 13:05:20', 12318);\n\n      expect(String(schedule)).to.equal('2015-01-02T13:05:20A03:25:18');\n    });\n  });\n});\n"
  },
  {
    "path": "test/TimePattern/RecurringTime.spec.js",
    "content": "'use strict';\n\nlet expect        = require('chai').expect;\nlet RecurringTime = require('../../lib/TimePattern/RecurringTime');\n\ndescribe('TimePattern/RecurringTime', () => {\n  it('should have weekday constants', () => {\n    expect(RecurringTime).to.have.property('WEDNESDAY');\n  });\n\n  describe('constructor', () => {\n    it('should set arguments', () => {\n      let schedule = new RecurringTime(RecurringTime.MONDAY|RecurringTime.WEEKEND, '13:04:02');\n\n      expect(schedule.daysOfWeek).to.equal(67);\n      expect(schedule.timeOfDay).to.equal('13:04:02');\n    });\n  });\n\n  describe('toString', () => {\n    it('should be expected format', () => {\n      let schedule = new RecurringTime(RecurringTime.WEEKEND, '23:02:03');\n\n      expect(String(schedule)).to.equal('W3/T23:02:03');\n    });\n  });\n});\n"
  },
  {
    "path": "test/TimePattern/Timer.spec.js",
    "content": "'use strict';\n\nlet expect = require('chai').expect;\nlet Timer  = require('../../lib/TimePattern/Timer');\n\ndescribe('TimePattern/Timer', () => {\n  describe('constructor', () => {\n    it('should accept seconds argument', () => {\n      let schedule = new Timer(10);\n\n      expect(schedule).to.have.property('seconds');\n      expect(schedule.seconds).to.equal(10);\n      expect(schedule.repeat).to.equal(null);\n    });\n\n    it('should accept seconds and repeat arguments', () => {\n      let schedule = new Timer(56, 3);\n\n      expect(schedule.seconds).to.equal(56);\n      expect(schedule).to.have.property('repeat');\n      expect(schedule.repeat).to.equal(3);\n    });\n  });\n\n  describe('toString', () => {\n    it('should be expected format with seconds', () => {\n      let schedule = new Timer(2382);\n\n      expect(String(schedule)).to.equal('PT00:39:42');\n    });\n\n    it('should be expected format with seconds and repeat', () => {\n      let schedule = new Timer(12350, 24);\n\n      expect(String(schedule)).to.equal('R24/PT03:25:50');\n    });\n  });\n});\n"
  },
  {
    "path": "test/mocha.opts",
    "content": "--recursive\n--ui bdd\n--check-leaks\n"
  }
]